0

I am trying to pass couple of cv::Mat object from one program to another, both implemented in C++ and preferably run in parallel. The cv::Mat does not have an image in it, so imread and imwrite are not useful here (we can not compress data with traditional image compressing methods). One solution would be writing the matrix in a file (CSV file for example), but since the program process too much information, the disk will be the bottleneck, besides, I soon will run out of disk space.

After some digging, I found pipes (name or unnamed) as a useful solution. I wrote two pilot programs: Producer.cpp:

int main(int argc, char* argv[])
{       
        Mat image;
        image = imread(argv[1]);
        cout << image;
        cout.flush();
        return 0;
}

Consumer.cpp:

int main(int argc, char* argv[])
{       
        Mat image;
        cin >> image;
        imshow("Image", image);
        waitKey();
        return 0;
}

Surprisingly, the second program will not compile.

mismatched types ‘_CharT2*’ and ‘cv::Mat’ cin >> image;

Which means (I guess) ">>" operator is not overloaded for cv::Mat. Even though we might be able to override the >> operator, since the matrix is big, and stdin and stdout are text based, it would not be the best neither the easiest way.

So, back to main question: What is the best way of passing a cv::Mat object (or potentially any other binary object) from one program to another?

dave
  • 4,812
  • 4
  • 25
  • 38
  • TCP/IP But this question can be answered in more than one way – GPPK Nov 13 '15 at 10:02
  • You can check [here](http://stackoverflow.com/a/32357875/5008845) how to serialize and deserialize a `Mat` – Miki Nov 13 '15 at 11:27
  • Thanks GPPK for the answer, TCP/IP is a good choice but how and why they are better than pipes? – Pejman Habashi Nov 13 '15 at 16:26
  • Thanks Miki for your response. The proposed solution was inspiring, even though based on my tests the speed boos, is something between 5 and 10 times faster (I believe it relates to system which runs the test). I'm going to mix that with named pipes which hopefully will solve my problem. I will post the solution soon after I finished it. – Pejman Habashi Nov 13 '15 at 19:35

2 Answers2

2

The Mat (or any other object) should be serialized in some way. The easy way of serializing in opencv is using FileStorage. Here is the sample codes:

producer:

int main(int argc, char* argv[])
{
    Mat image;
    image = imread(argv[1]);
    FileStorage fs("temp", FileStorage::WRITE);
    fs << "MyImage" << image;
    return 0;
}

consumer:

int main(int argc, char* argv[])
{
    Mat image;
    FileStorage fs("temp", FileStorage::READ);
    fs["MyImage"] >> image;
    imshow("Image", image);
    waitKey();
    return 0;
}

Where "temp" is the file name in which the data will be stored. The best way to run these programs in parallel without using fileSystem, is to define a named pipe "temp", in the proper place, before running programs in parallel:

>mkfifo temp
>./producer testFile.jpg | ./consumer

This way no disk is used and the programs can be run in parallel.

The fileStorage changes the binary content of Mat to ascii, which is time consuming. One may decide to serialize the content in binary as explained here and use the named pipes with them.

Community
  • 1
  • 1
  • I have tried float type variable with FileStorage; it also works. But is it possible to send & receive the variable on-fly? I mean real-time sending & receiving during the operation. – user1098761 Feb 01 '17 at 01:24
  • 1
    Yes, fifos are an excellent solution to send/receive data on the fly, but sometimes, you might need process synchronization. The simple examples above run in parallel and consumer consumes data as it becomes available. – Pejman Habashi Feb 01 '17 at 15:26
0

Write the file to disk, and remember to delete it as soon as you're done with it. The file cache will delay a physical write, and the rapid deletion the prevents the physical write.

Alternatively, store the data is shared memory.

MSalters
  • 173,980
  • 10
  • 155
  • 350