一 ,需求

在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()
        }
}

三,注意事项

利用单独的一个线程去解析相机或者视频流的图像,并通过信号和槽机制去通知更新