# Problem to send Mat images over TCP/IP

Hello community,

Actually, I capture images from a Gige camera on jetson TX2 (which runs with ubuntu). I process the image, and I stock it in Mat matrice. The image resolution is 3840*5120.

Then, I need to transfert that image toward windows computer. Windows is the server, and linux the client.

To send all kinds of type, I have to use a structure. So, from the client, I have (I don´t respect thje camera´s resolution here) :

client side

struct Image
{
cv::Mat img = cv::Mat::zeros(768, 1024, CV_8UC3);
};

Image imgTest = frame ;


....

error=send(sock, &imgTest, sizeof(imgTest), 0) ;*


server side

struct Image
{
cv::Mat img = cv::Mat::zeros(768, 1024, CV_8UC3);
};

Image imgTest ;*


...

if (recv(csock, (char *)&imgTest, sizeof(imgTest), 0) != SOCKET_ERROR){
std::cout << "Receive" << std::endl ;
}


The code crash. Why the argument of the function in windows and linux are differents ?

On linux, we have :

int send(int socket, void* buffer, size_t len, int flags);
int recv(int socket, void* buffer, size_t len, int flags);


On windows, we have :

int send(int socket, char* buffer, size_t len, int flags);
int recv(int socket, char* buffer, size_t len, int flags);


I cast the struct in "char *", and I know that is the problem. Someone has an idea to solve it ? I know there already is a page about that topic, but I am not interested by the solution. You suggest to send an array of char. In my case, the size of the array is 19,660,800 (I work with grayscale), means almost 20 Go only for the buffer, and my RAM is not big enought .

Thank you, NL37

edit retag close merge delete

3480*5120*3 = 53452800 (at least in my maths) so 53mb for color or ~17mb for grayscale

( 2020-03-05 07:09:05 -0500 )edit
1

and no, you cannot send a Mat object over the wire (it's non POD)

try with Mat.data instead, or better, compress it using imencode()

( 2020-03-05 07:22:32 -0500 )edit

Sort by » oldest newest most voted

First, your image is only 20MB, not 20GB; so your memory should be enough.

The problem is that the Mat class is only a header; the image data is kept elsewhere and managed separately (and you don't send it).

So instead of sending the Mat variable, send a (text) header containing the image size (img.rows, img.cols), image type and buffer size; then send the img.data as binary data. At the client side you should be able to recreate the Mat variable (Mat img(rows,cols,type,data);).

A simpler and more robust solution is to encode the image data to a buffer and send this buffer:

std::vector<uchar> buf;
std::vector<int> compression;
compression.push_back(CV_IMWRITE_JPEG_QUALITY);
compression.push_back(80);
cv::imencode(".JPG",img,buf,compression);


Then send the buf vector over the network. On the client side call img = imdecode(buf);.

This solution will also compress the image, so you'll gain in bandwidth. The example above uses JPG format with a compression factor of 80. You can increase the quality according to your needs, or use other formats, like lossless grayscale PNG (attention, PNG encoding for large images takes more time).

more

1

Hello,

Many thanks for your help ! I will try your method. Yes I know, I made a big mistake for about the storage .. Sorry. Actually, I don´t have to loose any informations. I use the format ".tiff" without any compressions. In that case, can I use :

compression.push_back(CV_IMWRITE_TIFF_QUALITY, COMPRESSION_NONE );

Thank you again !

( 2020-03-05 08:11:30 -0500 )edit

Official site

GitHub

Wiki

Documentation