一、配置环境:
QT5+opencv4.4库,电脑配置的是MSVC2015的编译器。
二、主要步骤:
不管是调用摄像头实时显示视频还是显示本地视频,QT中要注意好定时器的使用,即QTimer类。
建立QT工程的时候选择MainWindow类,然后选择创建Ui界面,工程新建好之后
这里是我添加好相机、视频、图片之后的状态,选择mainwindow类新建好工程之后就会出现上面的那种工具栏,使用很方便。
点击相机、视频、图片这几个菜单还可以添加子菜单,然后通过点击子菜单,采用connect函数完成信号与槽的链接。
剩下的就是信号槽的关联了,下面是我针对每个菜单建立的槽。
具体的代码如下:
.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 <QMainWindow>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <QTimer>
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 更新:已经解决了霍夫圆检测问题,可以实时跟踪视频检测视频中的圆。