一,需求
将相机的视频渲染到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。