如何在 QQuickPaintedItem 中以高效的方式绘制顺序图像
How to paint sequential image in efficient way in QQuickPaintedItem
出于某种原因,我需要将 opencv VideoCapture 包装在一个 class 中,它将在 Qt Quick 中使用。
有两个class,一个是Camera,一个是CameraView。 CameraView 继承自 QQuickPaintedItem.
相机class会定期获取图像。它通过 QObject::startTimer(int interval) 实现。 (例如,如果网络摄像头的 fps 为 30,则定时器间隔为 1000 / 30 - 8,8 为时间偏差)。一旦 Camera 获取图像,它会通过调用 CameraView::Update().
通知 CameraView 重新绘制
并且在 CameraView::paint(QPainter *) 中,CameraView 将从 Camera class 获取图像的副本并通过调用 QPainter::drawImage(...) 绘制该图像。
我在编码过程中遇到了一些问题:
我尝试用 QThread 替换时间事件以定期从相机获取图像。当我在 QThread 中调用 CameraView::Update() 时,CameraView 不会重新绘制。有什么问题吗?
在我的笔记本电脑中,当我让 CameraView 全屏绘制图像时,我发现有一个 python 程序变慢了。有没有另一种低成本高效的画图方式?
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.
必须从 Qt 中的 UI 线程触发 UI 更新,包括 QML。使 CameraView 暴露 public 插槽 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 应该像这样实现 updateImage
和 paint
:
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);
}
更新: 在我自己的 "camera" 线程类似 QML 输出的代码中,我还负责处理 UI 线程停顿时无法处理视频帧,以便信号发送方知道何时不 post 视频帧。但这值得另一个问题。或者可以在没有信号和槽但有条件变量的情况下重新实现整个示例。
出于某种原因,我需要将 opencv VideoCapture 包装在一个 class 中,它将在 Qt Quick 中使用。
有两个class,一个是Camera,一个是CameraView。 CameraView 继承自 QQuickPaintedItem.
相机class会定期获取图像。它通过 QObject::startTimer(int interval) 实现。 (例如,如果网络摄像头的 fps 为 30,则定时器间隔为 1000 / 30 - 8,8 为时间偏差)。一旦 Camera 获取图像,它会通过调用 CameraView::Update().
通知 CameraView 重新绘制并且在 CameraView::paint(QPainter *) 中,CameraView 将从 Camera class 获取图像的副本并通过调用 QPainter::drawImage(...) 绘制该图像。
我在编码过程中遇到了一些问题:
我尝试用 QThread 替换时间事件以定期从相机获取图像。当我在 QThread 中调用 CameraView::Update() 时,CameraView 不会重新绘制。有什么问题吗?
在我的笔记本电脑中,当我让 CameraView 全屏绘制图像时,我发现有一个 python 程序变慢了。有没有另一种低成本高效的画图方式?
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.
必须从 Qt 中的 UI 线程触发 UI 更新,包括 QML。使 CameraView 暴露 public 插槽 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 应该像这样实现 updateImage
和 paint
:
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);
}
更新: 在我自己的 "camera" 线程类似 QML 输出的代码中,我还负责处理 UI 线程停顿时无法处理视频帧,以便信号发送方知道何时不 post 视频帧。但这值得另一个问题。或者可以在没有信号和槽但有条件变量的情况下重新实现整个示例。