Envío de imágenes C ++ OpenCV a través de un socket

Estoy intentando implementar un servicio de transmisión usando OpenCV y sockets. El lado del servidor carga una imagen dada y la envía al cliente, que la recibe a través del socket y la muestra. Sin embargo, estoy teniendo muchos problemas al enviar los datos de la imagen y reconstruirla en el lado del cliente. Este es el código que he hecho hasta ahora:

Remitente de la imagen:

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  using namespace cv; using namespace std; void error(const char *msg) { perror(msg); exit(0); } int main(int argc, char *argv[]) { int sockfd, portno, n; struct sockaddr_in serv_addr; struct hostent *server; char buffer[256]; if (argc < 3) { fprintf(stderr,"usage %s hostname port\n", argv[0]); exit(0); } portno = atoi(argv[2]); sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd 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) error("ERROR connecting"); Mat image; image = imread(argv[3], CV_LOAD_IMAGE_COLOR); if(! image.data ) // Check for invalid input { cout << "Could not open or find the image" << std::endl ; return -1; } n = write(sockfd,image.data,image.total()*image.channels()); if (n < 0) error("ERROR writing to socket"); close(sockfd); namedWindow( "Client", CV_WINDOW_AUTOSIZE );// Create a window for display. imshow( "Client", image ); waitKey(0); return 0; } 

Receptor de imagen:

 #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  #include  using namespace cv; using namespace std; void error(const char *msg) { perror(msg); exit(1); } int main(int argc, char *argv[]) { int sockfd, newsockfd, portno; socklen_t clilen; char buffer[1024]; struct sockaddr_in serv_addr, cli_addr; int n; if (argc < 2) { fprintf(stderr,"ERROR, no port provided\n"); exit(1); } sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); bzero((char *) &serv_addr, sizeof(serv_addr)); portno = atoi(argv[1]); 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) error("ERROR on binding"); listen(sockfd,5); clilen = sizeof(cli_addr); newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERROR on accept"); bzero(buffer,1024); n = read(newsockfd,buffer,1023); if (n < 0) error("ERROR reading from socket"); Mat image(690,690,CV_8UC3,*buffer); imwrite("/home/securitas/images/prova.jpg",image); close(newsockfd); close(sockfd); namedWindow( "Server", CV_WINDOW_AUTOSIZE );// Create a window for display. imshow( "Server", image ); waitKey(0); return 0; } 

Todo lo que recibo en el lado del cliente es una imagen negra, nada más. ¿Alguna ayuda?

Obtenga Mat.data y envíe directamente al socket, el orden de los datos es BGR BGR BGR …. En el lado receptor asume que conoce el tamaño de la imagen. Después de recibir simplemente asigne el buffer recibido (BGR BGR … array) a una Mat.

Cliente:-

 Mat frame; frame = (frame.reshape(0,1)); // to make it continuous int imgSize = frame.total()*frame.elemSize(); // Send data here bytes = send(clientSock, frame.data, imgSize, 0)) 

Servidor:-

 Mat img = Mat::zeros( height,width, CV_8UC3); int imgSize = img.total()*img.elemSize(); uchar sockData[imgSize]; //Receive data here for (int i = 0; i < imgSize; i += bytes) { if ((bytes = recv(connectSock, sockData +i, imgSize - i, 0)) == -1) { quit("recv failed", 1); } } // Assign pixel value to img int ptr=0; for (int i = 0; i < img.rows; i++) { for (int j = 0; j < img.cols; j++) { img.at(i,j) = cv::Vec3b(sockData[ptr+ 0],sockData[ptr+1],sockData[ptr+2]); ptr=ptr+3; } } 
 bytes = send(clientSock, frame.data, imgSize, 0)); 

Esta statement está dando error en Visual Studio 12. Dice que .. ERROR: argumento de tipo “uchar *” es incompatible con el parámetro de tipo “const char *” en “” frame.data “”.

Desbordamiento de búfer. Y no estoy seguro de que el formato y el tamaño de la imagen sean los mismos -> debes serializar tu Mat honestamente, algo así como aquí .

La respuesta de Haris es correcta y funcionó para mí. Sin embargo, en lugar de ese código de servidor (imagen de construcción de datos uchar), también puede usar la forma más corta:

 int imgSize = img.total()*img.elemSize(); uchar sockData[imgSize]; for (int i = 0; i < imgSize; i += bytes) { if ((bytes = recv(connectSock, sockData +i, imgSize - i, 0)) == -1) quit("recv failed", 1); } // change the last loop to below statement Mat img(Size(HEIGHT, WIDTH), CV_8UC3, socketData); 

En Microsoft Visual Studio 2012, tengo una línea roja debajo de imgSize en sockData [imgSize] diciendo que la expresión debe tener un valor constante. Luego cambié int imgSize para const int imgSize. Todavía me muestra el mismo problema.

  Mat img = Mat::zeros(100,100, CV_8UC3); const int imgSize = img.total()*img.elemSize(); uchar sockData[imgSize];