我从硬件(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()
来自我的代码。抱歉,因为这个愚蠢的错误。
答案 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。