C++ 使用Qt显示图像流

C++ 使用Qt显示图像流,c++,qt,opengl,C++,Qt,Opengl,当前的解决方案如下所示: //paintlabel.h class PaintLabel : public QWidget { Q_OBJECT public: explicit PaintLabel(QWidget *parent = 0); public slots: void setImage(char *img_ptr, QSize img_size, int pitch); protected: void paintEvent(QPaintEven

当前的解决方案如下所示:

//paintlabel.h
class PaintLabel : public QWidget
{
    Q_OBJECT

public:
    explicit PaintLabel(QWidget *parent = 0);

public slots:
    void setImage(char *img_ptr, QSize img_size, int pitch);

protected:
    void paintEvent(QPaintEvent *event) override;

private:
    QImage image;

}

//paintlabel.cpp

PaintLabel::PaintLabel(QWidget *parent) : QWidget(parent)
{
    setAttribute(Qt::WA_NoSystemBackground, true);
}

void PaintLabel::setImageLive(char *img_ptr, QSize img_size, int pitch)
{
    image = QImage((uchar *)img_ptr, img_size.width(), img_size.height(), pitch, QImage::Format_RGB32).scaled(this->size());
    update();  
}

void PaintLabel::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    QPainter painter;
    painter.begin(this);
    if (!image.isNull()) {
        const QPoint p = QPoint(0,0);
        painter.drawImage(p, image);
    }
    painter.end();
}
我预计每秒20-40帧。问题是,性能随尺寸的变化而变化。画图的大小大约为fullHD,需要1-2毫秒。但是如果我将其大小调整为4k,它会变得非常滞后(16毫秒画图)。是否有任何方法可以实现相同的功能,但资源消耗较少


理论上,如果我将父类更改为QOpenGLWidget,则QPainter将以硬件加速运行。但是这样做,它运行得更慢。

首先,代码中的限制因素之一似乎是
scaled()
函数。试着把它拿出来,你会看到一些加速

另一个问题就是QImage的性能限制。有关更多信息,请参阅此问题

QPainter将使用软件光栅化器绘制QImage实例

有关更多信息,请参阅

您不能选择
QPixmap
,因为您的整个缓冲区也会更改每个帧

您可以尝试使用
QOpenGLPaintDevice
使
QPainter
使用硬件加速。您尝试的另一种方法是
QOpenGLWidget

QOpenGLWidget-画家也可以在QOpenGLWidget上打开。这是为了方便起见而提供的,因为从技术上讲,这与使用QOpenGLPaintDevice没有什么不同

参考上面相同的qt链接

是的,这在技术上应该更快,但由于您正在调整
小部件的大小,从而调整
OpenGL视口的大小,因此每次都会重新生成下面的缓冲区。因此,经济放缓要严重得多。请注意,QOpenGLWidget自行处理一些函数,如
glViewport()
。当您试图优化性能时,这是没有用的

这里有几个建议

  • 我认为主要的问题是如何处理QImage。我建议您设置自己的OpenGL场景,只需使用一个四边形渲染纹理,然后尝试在每一帧中写入纹理。扩展将在GPU上处理,因此肯定会更快

  • 或者,您可以使用
    glDrawPixels()
    将图像从主机内存(RAM)渲染到帧缓冲区。虽然这不会为您处理缩放。有关更多信息,请参阅

  • 我目前正在使用QGLWidget和自定义OpenGL纹理和绘制调用来实现快速更新(>60fps)。我观察到这比QImage/Qpixmap方法快8到10倍。请注意,我的纹理大小从未超过700x700。此外,我的图像始终存储在GPU内存中,并由映射的CUDA内核更新


    您肯定会看到一个加速,但我不能保证它会满足您的FPS要求。

    在OpenGL中,您可以使用双缓冲来避免这种情况。可能你有2个PaintLabel,在加载新图像之前不显示它。双缓冲并不能真正改变渲染速度非常慢的事实。我估计它是3-5帧每秒,而相机是25帧每秒。