信号/插槽OpenCV Mat在Qt中的不同线程上

时间:2014-08-13 14:37:53

标签: c++ multithreading qt opencv

我从硬件(PointGrey)相机聚合图像,并将它们放入专用(相机)线程中的opencv矩阵中。我想在另一个(gui)线程中运行的QWidget中显示这些图像。

如果图像聚合和gui在同一个线程中运行,那么一切都在内存方面很好,但是一旦相机在另一个线程中运行,我就会出现内存泄漏,因为opencv矩阵没有被正确删除

整个事情看起来如下:

 Thread A                         Thread B
+---------+                      +---------+
| Camera  |                      | QWidget |
+---------+                      +---------+
     |                                |
     | emit camFrame(frame);--------->|
     |                                |-> setImage(cv::Mat frame);
     |                                |

我将camFrame信号与QMainWindow实例中的setImage插槽连接:

mCameraThread = new QThread;
mCamera->moveToThread(mCameraThread);

/* connect camera with attached thread */
connect(mCameraThread, SIGNAL(started()), mCamera, SLOT(start()));
connect(mCamera, SIGNAL(stopped()), mCameraThread, SLOT(quit()));
connect(mCamera, SIGNAL(stopped()), mCamera, SLOT(deleteLater()));
connect(mCameraThread, SIGNAL(finished()), mCameraThread, SLOT(deleteLater()));

/* connect camera with camerawidget thread */
connect(mCamera, SIGNAL(camFrame(cv::Mat)), mCameraPreviewWidget, SLOT(setImage(cv::Mat)));

/* start camera in separate thread with high priority */
mCameraThread->start();
mCameraThread->setPriority(QThread::TimeCriticalPriority);

在将opencv矩阵发送到另一个线程时,我没有分配新的内存,所以我不知道为什么会发生内存泄漏。我在做:

Image rawImage;
mError = mCamera.RetrieveBuffer(&rawImage);

cv::Mat tmpFrame(rawImage.GetRows(), rawImage.GetCols(), CV_8UC1);
tmpFrame.data = rawImage.GetData();
cv::Mat actualFrame = tmpFrame.clone();
tmpFrame.release();
emit camFrame(actualFrame)

有人能指出我在这里可能出错的方向吗?提前致谢

固定

谢谢大家。上面的示例代码实际上很好。我的错误是我不小心按照代码两次启动了相机。在玩第二个帖子时,我忘记删除该行

mCamera->start()

来自我的代码。抱歉,因为这个愚蠢的错误。

2 个答案:

答案 0 :(得分:0)

不幸的是我还没有发表评论,因此答案是:

您是否通过Q_DECLARE_METATYPE注册了该类型? 因为Qt实际上并没有发送cv::Mat,而是使用cv::Mat的众多转换运算符之一。

Qt 5.3.1 Q_DECLARE_METATYPE的文件(重点和注释是我的):

  

添加Q_DECLARE_METATYPE()使所有基于模板的函数都知道类型,包括QVariant。请注意,如果您打算在排队信号和插槽连接[1]或QObject的属性系统中使用类型,那么必须调用qRegisterMetaType(),因为名称是在运行时解析的。

[1]默认情况下,多线程会发生这种情况。

答案 1 :(得分:0)

当指针(“frame.data = rawImage.GetData();”)分配数据时,OpenCV不会自动释放资源。您可能想制作副本或手动释放Mat。