一 ,需求
在qml的Rectangle中渲染视频。
二,实现
- 继承QQuickPaintedItem 在paint函数中,绘制QImage
#ifndef MyCamera_H
#define MyCamera_H
#include <QQuickPaintedItem>
#include <QImage>
#include <atomic>
class MyCamera : public QQuickPaintedItem
{
Q_OBJECT
public:
explicit MyCamera(QQuickItem *parent = nullptr);
~MyCamera();
//开始预览
Q_INVOKABLE void startPreview();
//停止预览
Q_INVOKABLE void stopPreview();
public slots:
void newData();
signals:
//通过信号和槽 通知更新数据
void sinewData();
private:
std::atomic<bool> isRuning{false};
cv::Mat curMat;
protected:
//将curMat绘制到界面上
void paint(QPainter *painter);
};
#endif // MyCamera_H
#include MyCamera.h
#include <QVector3D>
#include <QPainter>
#include <QtConcurrent>
#include <chrono>
#include <thread>
#include <opencv.hpp>
#include <opencv2/imgproc.hpp>
MyCamera::MyCamera(QQuickItem *parent) : QQuickPaintedItem(parent)
{ connect(this,&MyCamera::sinewData,this,&MyCamera::newData,Qt::QueuedConnection);
}
MyCamera::~MyCamera()
{
stopPreview();
}
void MyCamera::startPreview()
{
//此处可打开相机,从相机
isRuning=true;
QtConcurrent::run([&](){
//相机循环取图
while(isRuning){
cv::Mat mat;
if(camera->grabImage(mat)){
//降采样
cv::resize(mat,curMat,cv::Size(mat.cols/8,mat.rows/8),0,0,cv::INTER_NEAREST);
}
}
});
}
void MyCamera::stopPreview()
{
isRuning=false;
}
void MyCamera::newData(){
update();
}
void MyCamera::paint(QPainter *painter)
{
QImage img((const uchar*)(curMat.data),curMat.cols,curMat.rows,curMat.step, QImage::Format_Grayscale8);
painter->drawImage(this->boundingRect(),img);
}
- main.cpp中注册上述类型
qmlRegisterType<MyCamera>(MyCamera,1,0,MyCamera);
- qml使用此类型
import MyCamera 1.0
Rectangle{
id:root
//视频
MyCamera{
id:mycamera
anchors.fill: parent
visible: true
Component.onCompleted: {
mycamera.startPreview()
}
}
三,注意事项
利用单独的一个线程去解析相机或者视频流的图像,并通过信号和槽机制去通知更新