C++ OpenCV отправка изображения через сокет

Я пытаюсь реализовать потоковый сервис с помощью OpenCV и розетки. Сервер загружает изображение и отправляет его клиенту, который получает его через розетку и отображает его. Однако у меня много проблем с отправкой данных изображения и его реконструкцией на стороне клиента. Это код, который я сделал до сих пор:

изображения отправителя:

#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/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

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 portn", argv[0]);
       exit(0);
    }
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) 
        error("ERROR opening socket");
    server = gethostbyname(argv[1]);
    if (server == NULL) {
        fprintf(stderr,"ERROR, no such hostn");
        exit(0);
    }
    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) 
        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;
}

изображения приемника:

#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/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>

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 providedn");
         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; 
}

Al я получаю на стороне клиента черное изображение, больше ничего. Любой помочь?

5 ответов


Получить Мат.данные и сразу отправляют в гнездо, заказ данных БГР БГР БГР.... На принимающей стороне предполагается, что вы знаете размер изображения. После получения просто назначьте полученный буфер (BGR BGR... array) Мату.

клиент:-

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))

сервер:-

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<cv::Vec3b>(i,j) = cv::Vec3b(sockData[ptr+ 0],sockData[ptr+1],sockData[ptr+2]);
   ptr=ptr+3;
   }
  }

bytes = send(clientSock, frame.data, imgSize, 0));

этот оператор дает ошибку в Visual Studio 12.Так говорят.. Ошибка: аргумент типа "uchar *" несовместим с параметром типа " const char *" на "" кадре.данные.""


переполнение буфера. И я не уверен, что формат и размеры изображения одинаковы - > вы должны сериализовать свой коврик честно, что-то как тут.


ответ Хариса правильный и сработал для меня. Однако вместо этого кода сервера (построение изображения из данных uchar) вы также можете использовать более короткую форму:

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);

в Microsoft Visual Studio 2012 у меня есть красная линия под imgSize в sockData[imgSize], говорящая, что выражение должно иметь постоянное значение. Затем я изменил int imgSize на const int imgSize. Это все еще показывает мне ту же проблему.

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