我正在尝试使用来自覆盆子的c ++向我的Windows PC发送OpenCV Mat
。
我的代码工作正在发送和获取帧,但是这些图像是灰度级的,质量非常差。
客户端(Windows):
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string.h>
#include <sys/types.h>
#include <winsock2.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include "WS2tcpip.h"
#define bzero(b,len) (memset((b),'\0',(len)),(void)0)
#define bcopy(b1,b2,len) (memmove((b2),(b1),(len)),(void) 0)
using namespace std;
int main()
{
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int n;
// IMPORTANT
WSADATA Data;
WSAStartup(MAKEWORD(2, 2), &Data);
////////////
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
cout << "Error while opening socket"<<endl;
return -1;
}
bzero((char*)&serv_addr,sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
cout << "Error while binding." << endl;
return -1;
}
listen(sockfd, 5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr,&clilen);
if (newsockfd < 0) {
cout << "Error while accepting socket" << endl;
return -1;
}
cv::Mat img;
img = cv::Mat::zeros(480, 640, CV_8UC1);
int imgSize = img.total() * img.elemSize();
uchar *iptr = img.data;
int bytes = 0;
if (!img.isContinuous()) {
img = img.clone();
}
cout << "Img size: " << imgSize << endl;
while (1) {
if ((bytes = recv(newsockfd, (char *)iptr, imgSize, MSG_WAITALL)) == -1) {
cout << "Error while recv frame" << endl;
break;
}
cv::imshow("VIDEO CLIENT", img);
cv::waitKey(30);
}
// IMPORTANT
WSACleanup();
//////////////
return 0;
}
服务器端(Raspberry Pi):
#include <ctime>
#include <iostream>
#include <raspicam/raspicam_cv.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
int main (int argc, char **argv){
int sockfd,portno,n;
struct sockaddr_in serv_addr;
struct hostent *server;
portno=5001;
sockfd = socket(AF_INET,SOCK_STREAM,0);
if(sockfd<0){
cout << "Error while opening socket."<<endl;
return -1;
}else{
cout << "Socket is now openned."<<endl;
}
server = gethostbyname("192.168.1.10");
if(server ==NULL){
cout << "Host does not exist."<<endl;
return -1;
}else{
cout << "Valid host!"<<endl;
}
bzero((char *) &serv_addr,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char*)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0){
cout << "Error while trying to connect."<<endl;
return -1;
}
else{
cout << "Connected!"<<endl;
}
raspicam::RaspiCam_Cv cam;
cv::Mat image;
image = cv::Mat::zeros(480,640,CV_8UC1);
if (!image.isContinuous()){
image = image.clone();
}
int imageSize = image.total()*image.elemSize();
int bytes = 0;
cout << "img size: " << imageSize << endl;
cam.set(CV_CAP_PROP_FORMAT,CV_8UC1);
cout << "Opening camera..."<<endl;
if (!cam.open()){
cout << "Error while opening camera." << endl;
return -1;
}
while(1){
cout << "Capturing frame..." << endl;
cam.grab();
cam.retrieve(image);
if(!image.empty()){
if((bytes = send(sockfd,image.data,imageSize,0))<0){
cout << "Error while sending..";
break;
}
cout << "Frame sent sucessfuly" << endl;
cout << bytes << " bytes sent." <<endl;
}else{
cout << "Frame was empty"<<endl;
break;
}
}
cout << "Stopping camera..."<<endl;
cam.release();
return 0;
}
Here您可以看到我的客户端如何获取帧。
我不知道造成这个问题的原因。 捕获框架后我遗漏了什么吗?
答案 0 :(得分:5)
我不建议在计算机之间发送cv :: Mat - 特别是具有不同CPU架构,字节顺序,字长和内存填充的计算机。
将图像转换为非压缩(或无损压缩)格式,例如png并发送。
您可以使用cv::encode / cv:: decode在内存中创建图像格式,而无需读取/写入临时文件。
注意:imdecode根据图像格式(png,jpeg等)标题内的数据确定图像类型。接收者不需要知道大小或类型。