如何在 QQuickPaintedItem 中以有效的方式绘制顺序图像

Posted

技术标签:

【中文标题】如何在 QQuickPaintedItem 中以有效的方式绘制顺序图像【英文标题】:How to paint sequential image in efficient way in QQuickPaintedItem 【发布时间】:2017-02-07 02:14:14 【问题描述】:

出于某种原因,我需要将 opencv VideoCapture 包装在一个将在 Qt Quick 中使用的类中。

有两个类,一个是Camera,另一个是CameraView。 CameraView 继承自 QQuickPaintedItem。

Camera 类会定期获取图像。它通过 QObject::startTimer(int interval) 实现。 (例如,如果网络摄像头的 fps 为 30,则计时器间隔为 1000 / 30 - 8,8 为时间偏差)。一旦Camera得到图像,它就会通过调用CameraView::Update()来通知CameraView重新绘制。

在 CameraView::paint(QPainter *) 中,CameraView 会从 Camera 类中获取图像的副本,并通过调用 QPainter::drawImage(...) 来绘制该图像。

我在编码过程中遇到了一些问题:

    我尝试用 QThread 替换时间事件以定期从相机获取图像。当我在 QThread 中调用 CameraView::Update() 时,CameraView 不会重新绘制。有什么问题?

    在我的笔记本电脑中,当我让 CameraView 全屏绘制图像时,我发现一个 python 程序速度变慢。是不是还有一种成本更低、效率更高的绘画方式?

【问题讨论】:

【参考方案1】:

如何基于 QQuickPaintedItem C++ 高效更新 QML 项目 班级?我将一些预处理委托给专用线程而不是 UI 线程上的计时器,它不再更新 QML UI 中的图像。

在 Qt 包括 QML 中,必须从 UI 线程触发 UI 更新。使该 CameraView 公开公共插槽updateImage

class CameraView : public QQuickPaintedItem

    Q_OBJECT
    Q_DISABLE_COPY(CameraView)

public:
    CameraView(QQuickItem* parent = nullptr);

public slots:
    void updateImage(const QImage&);

protected:
    QImage m_image;
;

CameraView 应该像这样实现updateImagepaint

void CameraView::updateImage(const QImage& image)

    m_imageThumb = image; // does shallow copy of image data
    update();             // triggers actual update


void CameraView::paint(QPainter* painter)

    painter->drawImage(this->boundingRect(), m_image);

ClassOpenCvOnWorkerThread 应该启动它的工作线程并暴露 signalUiUpdate:

OpenCvOnWorkerThread::OpenCvOnWorkerThread()

    this->moveToThread(&m_workerThread);
    // the below will allow communication between threads
    connect(this, SIGNAL(signalUiUpdate(QImage)), m_cameraView, SLOT(updateImage(QImage)));

    m_workerThread.start();


void OpenCvOnWorkerThread::cvRead()

     QImage image;

     // OpenCV details available in your code
     // cv::read
     // make QImage from frame


     // deliver QImage to another thread
     emit signalUiUpdate(image);

更新:在我自己的“相机”线程类似 QML 输出的代码中,当 UI 线程无法处理视频帧时,我还负责处理 UI 线程停顿,以便信号发送者知道何时不处理发布视频帧。但这值得另一个问题。或者整个示例可以在没有信号和槽的情况下使用条件变量重新实现。

【讨论】:

非常感谢。我已经做到了。一件重要的事情是在 CameraView 中将 renderTarget 设置为 QQuickPaintedItem::FramebufferObject,它在我的笔记本电脑中改进了很多。 我的回答有帮助吗? 当然!谢谢

以上是关于如何在 QQuickPaintedItem 中以有效的方式绘制顺序图像的主要内容,如果未能解决你的问题,请参考以下文章

如何在 QQuickPaintedItem 中选择一个区域

在 QML 上异步更新多个 QQuickPaintedItem

在 QQuickPaintedItem 上用鼠标绘制

自定义 QQuickPaintedItem 中的渲染质量差

不能在 QML 中使用 C++ QQuickPaintedItem Singleton

要在屏幕上绘制一些小图块,我应该使用 QQuickItem 还是 QQuickPaintedItem?