A.J*_*A.J 3 qt qgraphicsscene qquickitem
出于某种原因,我需要将 opencv VideoCapture 包装在一个将在 Qt Quick 中使用的类中。
有两个类,一个是Camera,另一个是CameraView。CameraView 继承自 QQuickPaintedItem。
相机类将定期获取图像。它通过 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 程序变慢了。是另一种低成本高效的绘画方式吗?
如何基于 QQuickPaintedItem C++ 类高效更新 QML 项?我将一些预处理委托给专用线程而不是 UI 线程上的计时器,并且它不再更新 QML UI 中的图像。
从 Qt 中的 UI 线程(包括 QML)触发 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;
};
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
类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);
}
Run Code Online (Sandbox Code Playgroud)
更新:在我自己的“相机”线程类似 QML 输出的代码中,我还负责在无法处理视频帧时处理 UI 线程停顿,以便信号发送者知道何时不发布视频帧。但这值得另一个问题。或者可以在没有信号和槽但有条件变量的情况下重新实现整个示例。
| 归档时间: |
|
| 查看次数: |
2553 次 |
| 最近记录: |