OpenCV+Qt多线程打开多摄像头

现在网络上开源的OpenCV打开摄像头大多还是用死循环的方式,这里采用OpenCV+Qt多线程打开多个摄像头,并在一个界面上显示。本例程打开四个USB摄像头,三个型号一样,另一个型号不一样,原本想打开四个型号一样的,但是不知道为什么有一个就是打不开,现在还在查找原因。下面结合代码来讲解。

头文件thread_cam.h中定义了子线程类thread_cam,继承于QThread,功能是打开摄像头并将拍到的图片传回主线程显示,代码如下:

#ifndef THREAD_CAM_H
#define THREAD_CAM_H

#include <QThread>
#include <QTimer>
#include "opencv2/core/core.hpp"
#include "opencv2/videoio/videoio.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <QDebug>
#include <QImage>
using namespace cv;
using namespace std;

class thread_cam : public QThread
{
    Q_OBJECT
public:
    explicit thread_cam(QObject *parent = 0);
    thread_cam(int set_count=0)//记录打开了多少个摄像头
    {
        count=set_count;
    }

    void show_cam();

protected:
    void run();

private:
    int count;
    QTimer *timer;
    Mat img;
    QImage Qimg;
    VideoCapture cap;

signals:
    void return_QImage(QImage);//通过信号将子线程中采集的图片传回主线程
public slots:
};

#endif // THREAD_CAM_H

widget.h里面则不用多说了,直接看代码:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "thread_cam.h"

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void get_QImage1(QImage);
    void get_QImage2(QImage);
    void get_QImage3(QImage);
    void get_QImage4(QImage);

private:
    Ui::Widget *ui;

    thread_cam *thread_cam1;
    thread_cam *thread_cam2;
    thread_cam *thread_cam3;
    thread_cam *thread_cam4;

    QImage image;

};

#endif // WIDGET_H

thread_cam.cpp里是子线程类的实现,这里讲图片作为信号参数直接传回主程序会导致速度变慢,以后再想办法改进。

#include "thread_cam.h"
#include <QString>

thread_cam::thread_cam(QObject *parent) : QThread(parent)
{

}

void thread_cam::run()
{
    cap=VideoCapture(count);
    QString massage=QString("camera%1 opens fail").arg(count);

    if(!cap.isOpened())
    {
        qDebug()<<massage;
    }
    timer=new QTimer();
    timer->start(100);
    connect(timer,&QTimer::timeout,this,&thread_cam::show_cam);
    this->exec();//此句必须有,否则线程会立即结束

}

void thread_cam::show_cam()
{
    cap>>img;
    cvtColor(img,img,CV_BGR2RGB);//opencv中的图片以BGR格式保存,Qt中是RGB,故先转换格式再将Mat转为QImage
    QImage  Qimg((uchar*) img.data, img.cols, img.rows, img.step, QImage::Format_RGB888 );
    QString cam_name=QString("camera%1").arg(count);
    //imshow(cam_name.toStdString(),img);
    emit return_QImage(Qimg);


}

接下来就是主线程里处理的东西:

#include "widget.h"
#include "ui_widget.h"
#include <QThread>

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    thread_cam1=new thread_cam(0);
    thread_cam2=new thread_cam(1);
    thread_cam3=new thread_cam(2);
    thread_cam4=new thread_cam(3);

    connect(thread_cam1,&thread_cam::return_QImage,this,&Widget::get_QImage1);
    connect(thread_cam2,&thread_cam::return_QImage,this,&Widget::get_QImage2);
    connect(thread_cam3,&thread_cam::return_QImage,this,&Widget::get_QImage3);
    connect(thread_cam4,&thread_cam::return_QImage,this,&Widget::get_QImage4);

}

Widget::~Widget()
{
    delete ui;
}

void Widget::get_QImage1(QImage img_temp)
{
    image=img_temp;
    image.scaled(ui->label->width(),ui->label->height());
    ui->label->setPixmap(QPixmap::fromImage(image));
}

void Widget::get_QImage2(QImage img_temp)
{
    image=img_temp;
    image.scaled(ui->label_2->width(),ui->label_2->height());
    ui->label_2->setPixmap(QPixmap::fromImage(image));
}

void Widget::get_QImage3(QImage img_temp)
{
    image=img_temp;
    image.scaled(ui->label_3->width(),ui->label_3->height());
    ui->label_3->setPixmap(QPixmap::fromImage(image));
}

void Widget::get_QImage4(QImage img_temp)
{
    image=img_temp;
    image.scaled(ui->label_4->width(),ui->label_4->height());
    ui->label_4->setPixmap(QPixmap::fromImage(image));
}

void Widget::on_pushButton_clicked()
{
    thread_cam1->start();//启动线程
    thread_cam2->start();
    thread_cam3->start();
    thread_cam4->start();
}

void Widget::on_pushButton_2_clicked()
{
    thread_cam1->quit();//关闭线程
    thread_cam2->quit();
    thread_cam3->quit();
    thread_cam4->quit();
}

最后看看效果:

展开阅读全文

没有更多推荐了,返回首页