我正在努力解决记忆问题,我想我错过了一些东西,如果有人能指出我理解/做错了什么,我将不胜感激。
我想做的事
我的 gui 在主线程中运行。我正在一个单独的线程 T 上启动一个计算。这个计算的结果是一堆 opencv 图像。我想在计算期间在我的 gui 中显示它们。
我怎么理解我应该这样做
- 启动计算线程。
- 计算新图像时,将其转换为 QImage,将其包装在自定义 QEvent 中,然后将其发布到我的 gui。
- 只使用堆内存。
我是如何实现的
在我的计算线程中,当新图像准备好时:
std::shared_ptr<cv::Mat> cvimRGB = std::shared_ptr<cv::Mat>(new cv::Mat);
cv::Mat cvimBGR;
cv::Mat cvim = MyNewComputedImage;
cvim.convertTo(cvimBGR,CV_8UC3);
cv::cvtColor(cvimBGR,*cvimRGB,cv::COLOR_BGR2RGB);
std::shared_ptr<QImage> qim = std::shared_ptr<QImage>(
new QImage((uint8_t*) cvimRGB->data,cvimRGB->cols,cvimRGB->rows,cvimRGB->step,QImage::Format_RGB888));
ImageAddedEvent* iae = new ImageAddedEvent(qim,i);
QCoreApplication::postEvent(gui, iae);
在我的事件处理程序中:
bool mosaicage::event(QEvent * e){
if (e->type() == ImageAdded) {
ImageAddedEvent* ie = dynamic_cast<ImageAddedEvent*>(e);
QImage qim(*(ie->newImage));
QPixmap pm(QPixmap::fromImage(qim));
auto p = scene.addPixmap(pm);
images_on_display.push_back(p);
return true;
} else {
return QWidget::event(e);
}
}
我的自定义事件定义如下:
class ImageAddedEvent: public QEvent {
public:
ImageAddedEvent();
~ImageAddedEvent();
ImageAddedEvent(std::shared_ptr<QImage> im, int i);
std::shared_ptr<QImage> newImage;
int index;
};
发生什么了
在调试模式下,我得到了显示的废话。在发布模式下,我收到访问冲突错误。我对将 cv::Mat 转换为 qimage 的部分非常有信心,因为我没有更改它,我曾经从计算线程更新显示,但我学得更好。它虽然有效(当它没有崩溃时)。
我是如何解决的
问题出在 QImage 指向的内存中,它由我构建它的 cv::Mat 负责。如果我想保持这种构造 QImage 的方式,使用别人管理的数据,我必须保持数据有效。因此,我将 cv::Mat 移至自定义事件:
class ImageAddedEvent: public QEvent {
public:
ImageAddedEvent();
~ImageAddedEvent();
ImageAddedEvent(cv::Mat im, int i);
QImage newImage;
cv::Mat cvim;
int index;
};
我更改了事件的构造函数以使用 cv::Mat 数据初始化 QImage :
ImageAddedEvent::ImageAddedEvent(cv::Mat cvimRGB, int i) : QEvent(ImageAdded),
index(i),
cvim(cvimRGB)
{
newImage = QImage((uint8_t*) cvim.data,cvim.cols,cvim.rows,cvim.step,QImage::Format_RGB888);
}
现在我只需要将 cv::Mat 传递给我的事件构造函数:
cv::Mat cvimBGR,cvimRGB;
cv::Mat cvim = MyNewImage;
cvim.convertTo(cvimBGR,CV_8UC3);
cv::cvtColor(cvimBGR,cvimRGB,cv::COLOR_BGR2RGB);
ImageAddedEvent* iae = new ImageAddedEvent(cvimRGB,i);
QCoreApplication::postEvent(gui, iae);
等等,再次感谢您的帮助!