Ask Your Question
0

Problem to send Mat images over TCP/IP

asked 2020-03-05 06:58:03 -0600

NL37 gravatar image

updated 2020-03-05 07:05:58 -0600

berak gravatar image

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 flag offensive close merge delete

Comments

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

berak gravatar imageberak ( 2020-03-05 07:09:05 -0600 )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()

berak gravatar imageberak ( 2020-03-05 07:22:32 -0600 )edit

1 answer

Sort by » oldest newest most voted
2

answered 2020-03-05 07:29:12 -0600

kbarni gravatar image

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

edit flag offensive delete link more

Comments

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 !

NL37 gravatar imageNL37 ( 2020-03-05 08:11:30 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2020-03-05 06:58:03 -0600

Seen: 1,859 times

Last updated: Mar 05 '20