QT,C ++:在QGraphicsview上从相机绘制实时图像流的快速方法

时间:2016-04-25 14:01:04

标签: c++ qt opencv

我正在编写一个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是重要的,因为我想为图像添加叠加层。

2 个答案:

答案 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%。

然而,当我在发布中编译时,所有这三种方法都缝合均等