利用QGraphicsPixmapItem 渲染视频

利用QGraphicsPixmapItem 渲染视频

一,需求

将相机的视频渲染到QGraphicsPixmapItem 里,这样可以利用QGraphicsView这套系统在上边进行绘图

二,实现

  • 利用单独的一个线程取图,并转换为QImage后,放到队列里。然后激发信号,槽函数里,从队列取图,转成QPixmap后设置到QGraphicsPixmapItem上。
#ifndef MYCAMERA_H
#define MYCAMERA_H

#include <QObject>

#include <QObject>
#include <QImage>
#include <opencv2/opencv.hpp>
#include safequeue.h

class MyCamera : public QObject
{
    Q_OBJECT
public:
    explicit MyCamera(QObject *parent = nullptr);
    virtual ~MyCamera(){}

    QImage getImage();

    virtual void init()=0;
protected:
    //线程安全的队列 存入图片
    SafeQueue<QImage> imageQueue{1};

signals:
    void capture();
};

#endif // MYCAMERA_H
#include mycamera.h

MyCamera::MyCamera(QObject *parent)
    : QObject{parent}
{}

QImage MyCamera::getImage()
{
    return imageQueue.dequeue();
}
#ifndef MIPICAMERA_H
#define MIPICAMERA_H

#include mycamera.h

class MIPICamera : public MyCamera
{
    Q_OBJECT
public:
    explicit MIPICamera(QObject *parent = nullptr);
    ~MIPICamera();

    virtual void init() override;

private:
    //打开相机
    int openDevice();

private:
    std::atomic_bool bExit = true;
};

#endif // MIPICAMERA_H
#include mipicamera.h
#include log.h

MIPICamera::MIPICamera(QObject *parent)
    : MyCamera{parent}
{
    bExit=false;
}

MIPICamera::~MIPICamera()
{
    bExit=true;
}

void MIPICamera::init()
{
    std::thread t([&](){
        openDevice();
    });
    t.detach();
}

int MIPICamera::openDevice()
{
    cv::VideoCapture cap(0);
    if (!cap.isOpened()) {
        LOGE(Camera open failed!);
        return -1;
    }

    LOGI(Camera open!);
    cv::Mat frame;
    // 循环取图
    while (true) {
        cap >> frame;
        if (frame.empty()) {
            continue;
        }

        QImage image;
        if(frame.channels()==1){
            image = QImage((const uchar*)(frame.data),frame.cols,frame.rows,frame.step, QImage::Format_Grayscale8);
        }else if(frame.channels()==3){
            image = QImage((const uchar*)(frame.data),frame.cols,frame.rows,frame.step, QImage::Format_BGR888);
        }

        //qDebug()<<image <<image.width()<< <<frame.cols<< <<frame.channels();
        imageQueue.enqueue(image);
        emit capture();

        if(bExit)
        {
            break;
        }
    }
    cap.release();
    LOGI(Camera close!);
}
  • QGraphicsView初始化时,可以绑定信号和槽,从队列里取出QImage。

发表回复