2017-02-07 24 views
0

何らかの理由で、Qt Quickで使用されるクラスでopencv VideoCaptureをラップする必要があります。QQuickPaintedItemで効率的な連続画像をペイントする方法

2つのクラスがあり、1つはCamera、もう1つはCameraViewです。 CameraViewはQQuickPaintedItemから継承します。

カメラクラスは定期的に画像を取得します。それはQObject :: startTimer(int間隔)によって達成されました。 (たとえば、ウェブカメラのfpsが30の場合、タイマー間隔は1000/30 - 8、8は時間のずれです)。 Cameraが画像を取得すると、CameraView :: Update()を呼び出すことによって再描画するようにCameraViewに通知します。

CameraView :: paint(QPainter *)では、CameraViewはCameraクラスからイメージのコピーを取得し、このイメージをQPainter :: drawImage(...)コールでペイントします。

私はコーディングの過程でいくつかの問題だ:

  1. 私は定期的にカメラから画像を取得するためにQThreadとタイムイベントを交換しようとします。 QThreadでCameraView :: Update()を呼び出すと、CameraViewは再描画しません。何が問題ですか?

  2. 私のラップトップでは、CameraViewで画像をフルスクリーンでペイントすると、Pythonプログラムが遅くなることがわかりました。低コストで効率的に画像をペイントする別の方法はありますか?

答えて

1

にはどうすれば効率的にQQuickPaintedItem C++ クラスに基づいてQMLのアイテムを更新することができますか? UIスレッドのタイマー の代わりに、専用のスレッドにいくつかの前処理を委任し、QML UIの画像をもう更新しません。

QMLを含むQtのUIスレッドからのUI更新をトリガすることは必須です。 PublicView updateImageを公開するようにCameraViewを設定します。

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); 
} 

クラスOpenCvOnWorkerThreadは、そのワーカースレッドを起動して、公開する必要があり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:私自身のコードで用同様のQML出力を「カメラ」スレッドから処理します。ビデオフレームを処理することができないときにUIスレッドが停止し、信号送信者はビデオフレームをポストしないときを知る。しかしそれは別の質問に値する。または、この全体の例は、信号とスロットを使用せずに条件変数を使用して再実装できます。

+1

ありがとうございます。私はそれを達成しました。また、CameraViewでrenderTargetがQQuickPaintedItem :: FramebufferObjectに設定されていることが重要です。 –

+0

私の答えは助けになったのですか? – AlexanderVX

+0

ありがとうございました –

関連する問題