【问题标题】:What is the best way to transfer a cv::Mat object between different processes?在不同进程之间传输 cv::Mat 对象的最佳方法是什么?
【发布时间】:2015-11-13 03:05:02
【问题描述】:

我正在尝试将几个 cv::Mat 对象从一个程序传递到另一个程序,它们都是用 C++ 实现的,最好是并行运行。 cv::Mat 里面没有图像,所以 imread 和 imwrite 在这里没有用(我们不能用传统的图像压缩方法来压缩数据)。一种解决方案是将矩阵写入文件(例如CSV文件),但由于程序处理的信息太多,磁盘将成为瓶颈,而且我很快就会耗尽磁盘空间。

经过一番挖掘,我发现管道(名称或未命名)是一种有用的解决方案。我写了两个试点程序: 生产者.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;
}

令人惊讶的是,第二个程序无法编译。

不匹配的类型‘_CharT2*’和‘cv::Mat’ cin >> 图像;

这意味着(我猜)“>>”运算符没有为 cv::Mat 重载。即使我们可以覆盖 >> 运算符,因为矩阵很大,而且标准输入和标准输出是基于文本的,它既不是最好的也不是最简单的方法。

所以,回到主要问题:将 cv::Mat 对象(或任何其他二进制对象)从一个程序传递到另一个程序的最佳方式是什么?

【问题讨论】:

  • TCP/IP 但这个问题的答案不止一种
  • 你可以查看here如何序列化和反序列化Mat
  • 感谢 GPPK 的回答,TCP/IP 是一个不错的选择,但它们如何以及为什么比管道更好?
  • 感谢三木的回复。所提出的解决方案是鼓舞人心的,即使根据我的测试,速度提升速度要快 5 到 10 倍(我相信它与运行测试的系统有关)。我将把它与命名管道混合,希望能解决我的问题。完成后我会尽快发布解决方案。

标签: c++ opencv pipe named-pipes


【解决方案1】:

Mat(或任何其他对象)应该以某种方式序列化。在 opencv 中序列化的简单方法是使用 FileStorage。以下是示例代码:

制作人:

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

消费者:

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

其中“temp”是存储数据的文件名。在不使用文件系统的情况下并行运行这些程序的最佳方法是在并行运行程序之前在适当的位置定义一个命名管道“temp”:

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

这种方式不使用磁盘,程序可以并行运行。

fileStorage将Mat的二进制内容改成ascii,比较耗时。人们可能会决定按照here 的解释以二进制形式序列化内容,并使用命名管道。

【讨论】:

  • 我尝试过使用 FileStorage 的浮点型变量;它也有效。但是是否可以即时发送和接收变量?我的意思是在操作过程中实时发送和接收。
  • 是的,fifos 是即时发送/接收数据的绝佳解决方案,但有时您可能需要进程同步。上面的简单示例并行运行,消费者在数据可用时使用它。
【解决方案2】:

将文件写入磁盘,并记住在完成后立即将其删除。文件缓存会延迟物理写入,快速删除会阻止物理写入。

或者,存储数据是共享内存。

【讨论】:

  • 写入磁盘不是我的选项。恐怕文件缓存比我的数据小得多(我可能有 4GB 的数据),在这种情况下管道要好得多。
  • @PejmanHabashi:通常购买一些额外的内存比想出一个复杂的解决方法更便宜。不过,请尝试共享内存。
  • @MSaltersL 感谢您指出这一点。磁盘空间没什么大不了的,我有很多,还有10GB的内存。速度在这里更重要,与 RAM 相比,磁盘太懒了。
  • 什么磁盘速度?有了足够的 RAM,文件就会保留在缓存中。
  • 我明白你的意思,但是文件比命名管道有什么好处?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 2018-05-31
  • 1970-01-01
相关资源
最近更新 更多