How to paint sequential image in efficient way in QQuickPaintedItem

a 夏天 提交于 2019-12-05 04:29:50

问题


For some reason, I needs to wrap opencv VideoCapture in a class which will be used in Qt Quick.

There are two classes, one is Camera, other is CameraView. CameraView inheritd from QQuickPaintedItem.

Camera class will get image periodically. It achieved by QObject::startTimer(int interval). (e.g. If fps of the webcam is 30, the timer interval is 1000 / 30 - 8, 8 is deviation of time). Once Camera has get image, it notifies CameraView to repaint by calling CameraView::Update().

And in CameraView::paint(QPainter *), CameraView will get an copy of image from Camera class and paints this image by call QPainter::drawImage(...).

I got some problems in process of coding:

  1. I try to replace time event with QThread to get image from camera periodically. When I call CameraView::Update() in QThread, CameraView doesn't repaint. What is the problem?

  2. In my laptop, when I make the CameraView painting the image in fullscreen, I found one python program slow down. Is another way to paint image with lower cost and efficient?


回答1:


How can I efficiently update QML item based on QQuickPaintedItem C++ class? I delegated some preprocesssing to dedicated thread instead of a timer on UI thread and it does not update the image in QML UI anymore.

It is a mandatory to trigger UI update from UI thread in Qt including QML. Make that CameraView to expose public slot 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 should implement updateImage and paint like that:

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 should start its worker thread and expose 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);
}

UPDATE: In my own code for similar QML output from "camera" thread I also take care of handling the UI thread stall when it is unable to process video frames so the signal sender knows when not to post video frames. But that worth another question. Or this whole example can be reimplemented without signal and slot but with condition variable.



来源:https://stackoverflow.com/questions/42080565/how-to-paint-sequential-image-in-efficient-way-in-qquickpainteditem

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!