QT5+opencv4调用摄像头实时显示和本地视频显示,图片显示

一、配置环境:
QT5+opencv4.4库,电脑配置的是MSVC2015的编译器。
二、主要步骤:
不管是调用摄像头实时显示视频还是显示本地视频,QT中要注意好定时器的使用,即QTimer类。
建立QT工程的时候选择MainWindow类,然后选择创建Ui界面,工程新建好之后QT5+opencv4调用摄像头实时显示和本地视频显示,图片显示_第1张图片
这里是我添加好相机、视频、图片之后的状态,选择mainwindow类新建好工程之后就会出现上面的那种工具栏,使用很方便。
点击相机、视频、图片这几个菜单还可以添加子菜单,然后通过点击子菜单,采用connect函数完成信号与槽的链接。
剩下的就是信号槽的关联了,下面是我针对每个菜单建立的槽。
QT5+opencv4调用摄像头实时显示和本地视频显示,图片显示_第2张图片

具体的代码如下:
.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    timer = new QTimer(this);
    image = new QImage();
    if(CameraFlag == 1)
        connect(timer,SIGNAL(timeout()),this,SLOT(readFarme()));//开启摄像头读取视频
    else
        connect(timer,SIGNAL(timeout()),this,SLOT(ReadVideos()));//读取本地视频文件
    connect(ui->Open,SIGNAL(clicked()),this,SLOT(on_Open_triggered()));
    connect(ui->Stop,SIGNAL(clicked()),this,SLOT(on_Stop_triggered()));
}

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

//打开摄像头
void MainWindow::on_Open_triggered()
{
    CameraFlag = 1;
    cap.open(0);
    timer->start(33);
}

//关闭摄像头
void MainWindow::on_Stop_triggered()
{
    //停止读取数据
    CameraFlag = 0;
    timer->stop();
    cap.release();
    ui->cameraview->clear();
}

//读取图像
void MainWindow::readFarme()
{
    cap.read(src_image);
    QImage image = MatImageToQt(src_image);

    //设置显示图像窗口跟随wiget窗口动态变化
    ui->cameraview->resize(ui->centralWidget->size());

    ui->cameraview->setPixmap(QPixmap::fromImage(image));//显示当前帧
}

//Mat转换成为QImage
QImage MainWindow::MatImageToQt(const cv::Mat &src)
{
    if(src.type() == CV_8UC1)
    {
        //使用给定图像的大小和格式构造图像
        QImage qimage(src.cols,src.rows,QImage::Format_Indexed8);
        //扩展颜色表的颜色数目
        qimage.setColorCount(256);

        //在给定的索引设置颜色
        for(int i=0;i<256;i++)
        {
            //得到黑白图像
            qimage.setColor(i,qRgb(i,i,i));
        }
        uchar *psrc = src.data;
        for(int row =0;row<src.rows;row++)
        {
            //遍历像素指针
            uchar *pdest = qimage.scanLine(row);
            memcpy(pdest,psrc,src.cols);
            psrc += src.step;
        }
        return qimage;

    }
    else if(src.type() == CV_8UC3)
    {
        const uchar *psrc = (const uchar*)src.data;
        QImage qimage(psrc,src.cols,src.rows,src.step,QImage::Format_RGB888);
        return qimage.rgbSwapped();
    }
    else if(src.type() == CV_8UC4)
    {
        const uchar *psrc = (const uchar*)src.data;
        QImage qimage(psrc,src.cols,src.rows,src.step,QImage::Format_ARGB32);
        return qimage.copy();
    }
    else
        return QImage();
}

//图像处理 找霍夫圆
cv::Mat MainWindow::FindCricleInCurrentImage(cv::Mat &src)
{
    cv::Mat dst;
    cv::medianBlur(src,src,3);//中值滤波
    cv::cvtColor(src,dst,cv::COLOR_BGR2GRAY);//转灰度图
    cv::GaussianBlur(dst,dst,cv::Size(3,3),3);
    cv::Canny(dst,dst,130,150,5);
    std::vector<cv::Vec3f> circles;
    cv::HoughCircles(dst,circles,cv::HOUGH_GRADIENT,1,10,100,100,10,150);
     for(std::size_t i=0;i<circles.size();i++)
     {
         cv::Vec3f c = circles[i];
         cv::circle(dst,cv::Point(c[0],c[1]),c[2],cv::Scalar(155,50,255),3,8,0);
     }
    return dst;
}


//读取视频文件
void MainWindow::ReadVideos()
{
    cap >> src_image;//逐帧读入图像
    cv::resize(src_image,src_image,cv::Size(640,480));//重新设置图像大小
    //src_image = FindCricleInCurrentImage(src_image);//找霍夫圆
    QImage qImage = MatImageToQt(src_image);//转为qt识别的图像
    //设置显示图像窗口跟随wiget窗口动态变化
    ui->cameraview->resize(ui->centralWidget->size());
    QPixmap qp;
    ui->cameraview->setPixmap(qp.fromImage(qImage));
    //ui->cameraview->setPixmap(QPixmap::fromImage(qImage));//如果类没有通过对象实例化则采用::调用
}

//开始载入视频
void MainWindow::on_startload_triggered()
{
    CameraFlag = 0;
    cap.open("movement.mp4");
    timer->start(50);//开始⏲,时间到33ms之后,触发signal信号,执行readvideos函数
}

//停止载入视频
void MainWindow::on_stopload_triggered()
{
    CameraFlag = 0;
    timer->stop();//关闭计时
    cap.release();//释放对象
    ui->cameraview->clear();//清除相机界面显示内容
}

//载入图片
void MainWindow::on_pictureload_triggered()
{
    src_image = cv::imread("test.jpg");
    cv::resize(src_image,src_image,cv::Size(600,400));//重新设置图像大小
    QImage qImage = MatImageToQt(src_image);//转为qt识别的图像
    //ui->cameraview->resize(ui->centralWidget->size());//跟随窗口大小变化
    ui->cameraview->setPixmap(QPixmap::fromImage(qImage));

}

.h文件中只是添加了一些函数的声明,和一些对象指针的定义。

#ifndef MAINWINDOW_H
#define MAINWINDOW_H


#include 
#include 
#include 
#include 
#include 
#include 

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    //Mat转QLabel
    QImage MatImageToQt(const cv::Mat &src);    
    //图像处理
    cv::Mat FindCricleInCurrentImage(cv::Mat &src);

    ~MainWindow();

private slots:
    void readFarme(); //读取摄像头实时视频

    void ReadVideos();//读取视频文件

    void on_Open_triggered();//开启摄像头

    void on_Stop_triggered();//关闭摄像头

    void on_startload_triggered();

    void on_stopload_triggered();

    void on_pictureload_triggered();

private:
    Ui::MainWindow *ui;
    cv::VideoCapture cap;
    cv::Mat src_image;
    QTimer *timer;
    QImage *image;
    bool CameraFlag;//相机标志位
};

#endif // MAINWINDOW_H

本来我想在视频中检测目标物体圆柱体的位置,然后通过霍夫圆检测找出来圆的位置,并显示在视频中,但是实验的时候发现根本不行,因为霍夫圆检测是一个很耗费时间的方法,在读入每一帧视频或者摄像头拍摄到一帧图像时,距离下一帧的图像采集时间很短,根本不够霍夫圆检测的。
不知道广大网友有什么好的方法,欢迎交流分享经验。

2020/10/30 更新:已经解决了霍夫圆检测问题,可以实时跟踪视频检测视频中的圆。

你可能感兴趣的:(QT5开发,opencv,qt5,msvc,c++,视频处理)