QT,C++:在QGraphicsview上从相机绘制实时图像流的快速方法
QT, C++: fast way to draw live image stream from camera on QGraphicsview
我正在编写一个QT GUI应用程序,其中连接的摄像机的实时流显示在QGraphicsview上。因此,openCV图像首先被转换为QImage,而不是QPixmap。这被添加到 QGraphicsView 的 QGraphicsScene 中。
带宽不是问题,相机通过以太网或USB连接。
我正在使用Visual Studio 2012中的Analyze Toole构建测试性能,它表明到QPixmap的转换非常慢,并且需要60%的计算时间(显示图像),因此我最终得到1 FPS左右。图像是2560年到1920年甚至更大。缩放 cv::P tr 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很重要,因为我想为图像添加叠加层。
我已经找到了一个适合我的解决方案,但也用不同的方法和它们的性能进行了一些测试:
方法一即使在调试模式下也能达到高性能,并且仅占用绘图过程执行时间的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% 的绘图工作量。
但是,当我在版本中编译时,所有三种方法的性能都非常相似。
这是我通常做的事情。 使用使用现有缓冲区的 QImage 构造函数之一,然后对其余缓冲区使用 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 位对齐的,则可以使用采用 bytesPerLine
参数的构造函数之一。
编辑:
如果您的图像是 32 位,那么您可以写入。
QPixmap pixmap = QPixmap::fromImage( QImage(
reinterpret_cast<uchar const*>( color_image->imageData ),
color_image->width,
color_image->height,
QImage::Format_RGB32 ) );
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 在本地网络中通过OpenCV(C++)实时流式传输图像
- 从实时摄影机馈送而不是图像中按形状跟踪对象
- C++:灰度位图标题和实时绘画+opencv图像处理
- 耗时的 Tensorflow C++会话>运行 - 用于实时推理的图像
- 实时图像处理:HSV图像中的噪声(openCV)
- 将实时图像从ROS转换为GSTREAMER视频
- OpenCv中实时视频流的图像拼接
- 实时应用中图像采集和图像处理的设计模式或最佳实践
- QT,C++:在QGraphicsview上从相机绘制实时图像流的快速方法
- 实时检测图像是否不同
- 打开简历.从网络摄像头的实时馈送中复制或裁剪图像,而不会泄漏内存
- 如何将opencv图像读取为咖啡格式以进行实时预测
- gstreamer 管道代码,用于通过来自相机的实时流式传输而不是图像显示文本
- 从图像创建实时RTP流
- Opencv/在线程中录制实时视频,在另一个线程中处理图像
- 如何获得EVF实时图像的尺寸和格式
- 多图像实时SIFT描述符匹配c++ /OpenCV
- 佳能EDSDK如何获得实时视图图像的宽度和高度