【问题标题】:QT, C++: fast way to draw live image stream from camera on QGraphicsviewQT、C++:在 QGraphicsview 上从摄像头绘制实时图像流的快速方法
【发布时间】:2016-08-18 23:26:09
【问题描述】:

我正在编写一个 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 我从 Thomas 的答案中测试了该方法,但它和我的方法一样慢。

QPixmap m_pixmap = QPixmap::fromImage(QImage(reinterpret_cast<uchar const*>(color_image->imageData), 
color_image->width, 
color_image->height, 
QImage::Format_RGB888));

编辑 3 我尝试采纳 Thomas 的第二个建议:

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 很重要,因为我想为图像添加叠加层。

【问题讨论】:

  • 发布一些关于如何进行转换的代码。
  • 您不能使用IPL_DEPTH_32F。你应该使用类似cvCreateImage(cvGetSize(stream_image), IPL_DEPTH_8U, 4) 的东西。对于 32 位,我的意思是每种颜色 3x8 位 + Alpha 通道。

标签: c++ qt opencv


【解决方案1】:

我找到了一个适合我的解决方案,但也用不同的方法进行了一些测试以及它们的性能:

方法一即使在调试模式下也很高效,并且只占用绘图程序执行时间的 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%。

然而,当我编译发布版时,所有三种方法都性能非常接近

【讨论】:

    【解决方案2】:

    这是我通常做的。使用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 ) );
    

    【讨论】:

    • 如果 QImage 以您的方式构建,QPixmap::fromImage() 会更快吗?那么如何从 cv::Ptr stream_src 获取 std::vector image_dst?
    • 我认为 Format_RGB888 是性能杀手,因为每个像素都必须从 24 位更改为 32 位。如果您将cvCreateImage 返回的格式更改为 32 位,它将提高性能。那么你可以使用color_image-&gt;imageData作为数据。
    • 我不得不使用QImage::Format_RGBA8888QImage::Format_ARGB32QImage::Format_RGB32 不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 2017-05-27
    • 2017-04-03
    相关资源
    最近更新 更多