c++ - How to send OpenCV Mat throught socket -
i trying send opencv mat
throught tcp using c++ raspberry windows pc. code working , sending , getting frames, images on gray scale , bad quality.
client side (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; }
server side (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 openned."<<endl; } server = gethostbyname("192.168.1.10"); if(server ==null){ cout << "host 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 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 empty"<<endl; break; } } cout << "stopping camera..."<<endl; cam.release(); return 0; }
here can see how client side gets frames.
i not know causing problem. missing after capturing frame?
i wouldn't recommend sending cv::mat bewtween computers - computers different cpu architecture, byte ordering, word length , memory padding.
convert image non-compressed (or losslessly compressed) format such png , send that.
you can use cv::encode / cv:: decode create image format in memory without having read/write temp file.
note: imdecode determines image type data inside image format (png, jpeg etc) header. receiver doesn't need know size or type.
Comments
Post a Comment