我正在编写一个QT GUI应用程序,在QGraphicsview上显示连接摄像机的实时流。因此,openCV图像首先转换为QImage而不是QPixmap。这被添加到QGraphicsView的QGraphicsScene中。
带宽不是问题,相机通过以太网或USB连接。
我正在使用Visual Studio 2012中的Analyze Toole构建测试性能,它显示转换到QPixmap非常慢并占用了60%的计算时间(显示图像),因此我最终得到1 FPS左右。这些图像是1920年的2560甚至更大。缩放cv :: Ptr stream_image以将其转换为QImage可以显着提高性能,但我需要图像中的所有图像细节。
修改 以下是我如何进行转换的一些代码:
cv::Ptr<IplImage> color_image;
// stream_image is a cv::Ptr<IplImage> and holds the current image from the camera
if (stream_image->nChannels != 3) {
color_image = cvCreateImage(cvGetSize(stream_image), IPL_DEPTH_8U, 3);
cv::Mat gr(stream_image);
cv::Mat col(color_image);
cv::cvtColor(gr, col, CV_GRAY2BGR);
}
else {
color_image = stream_image;
}
QImage *tmp = new QImage(color_image->width, color_image->height, QImage::Format_RGB888);
memcpy(tmp->bits(), color_image->imageData, color_image->width * color_image->height * 3);
// update Scene
m_pixmap = QPixmap::fromImage(*tmp); // this line takes the most time!!!
m_scene->clear();
QGraphicsPixmapItem *item = m_scene->addPixmap(m_pixmap);
m_scene->setSceneRect(0,0, m_pixmap.width(), m_pixmap.height());
delete tmp;
m_ui->graphicsView->fitInView(m_scene.sceneRect(),Qt::KeepAspectRatio);
m_ui->graphicsView->update();
编辑2 我从托马斯的回答中测试了这个方法,但它和我的方法一样慢。
QPixmap m_pixmap = QPixmap::fromImage(QImage(reinterpret_cast<uchar const*>(color_image->imageData),
color_image->width,
color_image->height,
QImage::Format_RGB888));
编辑3 我试图将托马斯的第二个建议纳入其中:
color_image = cvCreateImage(cvGetSize(resized_image), IPL_DEPTH_32F, 3);
//[...]
QPixmap m_pixmap = QPixmap::fromImage(QImage(
reinterpret_cast<uchar const*>( color_image->imageData),
color_image->width,
color_image->height,
QImage::Format_RGB32));
但是当调用Widget的drawEvent时崩溃。
问:有没有办法在QGraphicsView中显示图像流而不先将其转换为QPixmap或任何其他快速/高效的方式? QGraphicsView是重要的,因为我想为图像添加叠加层。答案 0 :(得分:0)
这就是我通常做的事情。使用其中一个constructors for QImage that uses an existing buffer,然后使用QPixmap::fromImage
。缓冲区的格式应与显示兼容,例如QImage::Format_RGB32
。在此示例中,矢量用作图像的存储。
std::vector<QRgb> image( 2560 * 1920 );
QPixmap pixmap = QPixmap::fromImage( QImage(
reinterpret_cast<uchar const*>( image.data() ),
2560,
1920,
QImage::Format_RGB32 ) );
注意对齐约束。如果alignemnt不是32位对齐的,则可以使用constructors that takes a bytesPerLine
参数之一。
修改强>
如果您的图片是32位,那么您可以写。
QPixmap pixmap = QPixmap::fromImage( QImage(
reinterpret_cast<uchar const*>( color_image->imageData ),
color_image->width,
color_image->height,
QImage::Format_RGB32 ) );
答案 1 :(得分:0)
我找到了一个适合我的解决方案,但也尝试了一些不同的方法以及它们的表现:
方法一即使在调试模式下仍然具有高性能,并且仅占绘图过程执行时间的23.7%(在VS2012中使用ANALYZE):
color_image = cvCreateImage(cvGetSize(stream_image), IPL_DEPTH_8U, 4);
cv::Mat gr(stream_image);
cv::Mat col(color_image);
cv::cvtColor(gr, col, CV_GRAY2RGBA,4);
QPixmap m_pixmap = QPixmap::fromImage(QImage(reinterpret_cast<uchar const*>( color_image->imageData),
color_image->width,
color_image->height,
QImage::Format_ARGB32));
方法二在调试模式下仍然具有42.1%的执行时间。当在QPixmap :: fromeImage中使用以下枚举
时QImage::Format_RGBA8888
方法三是我在问题中展示的那个,它在调试版本中的速度非常慢,占绘图工作量的68.3%。
然而,当我在发布中编译时,所有这三种方法都缝合均等。