实验室有个小伙伴是搞人脸识别的,所以近期我打算结合QT做一个人脸识别的项目,所以配置了一下QT中的OpenCV环境,之前是配置了visual stdio环境中的opencv,但是QT的又不一样。
这篇文章主要参考了这两个地方:B站视频:OpenCV入门1:Qt5.142搭建OpenCV4.51学习环境 和 CSDN博客:Qt配置OpenCV教程,亲测已试过(详细版)
第一步去官网下载OpenCV-4.5.1,由于之前官网下载不了,因此我这边给出一个百度网盘链接,提取码5205。
下载好了之后会得到这样一个图标,双击运行即可:
安装的目录我是选择当前的这个文件夹,看到网上说最好和qt是一个盘符的,也正好我的qt是安装在d盘的。
安装好之后会得到一个文件夹,里面包含构建好的build和source,其中build指的是微软平台编辑器可以直接运行的环境,source则是需要我们利用cmake去转换的文件,因为qt使用的是MinGW编译器(底层是gcc和g++),所以需要我们自行编译。
(CMAKE的安装步骤我忽略了,因为这个我之前已经装过,想了解这一步的小伙伴可以查看这篇文章 CSDN博客:Qt配置OpenCV教程,亲测已试过(详细版))
打开CMAKE,打开OpenCV的source文件路径,选择目标文件的生成路径,我设置的是D:/Opencv/opencv/Qt_OpenCV_Build
,如下图所示:
之后点击左下角的Configure:
之后会弹出一个指定的本地编译器,这个就选择MinGW,如下图所示:
下一步会要求我们选择编译c文件和c++文件的编译器(第三个那个Fortran不用管),这里我们用QT中的gcc和g++;QT的这两个工具的路径如下图所示:
选择好之后CMAKE就开始工作了,下图红色字体表示的是有些错误,或者编译未通过,这个需要我们按照他的提示去填一些内容。
编译完之后,有些错误我们先不管,先下拉,找到with_qt和with_open_gl,把这两个打上勾,然后继续点击configure。其中with_open_gl也是经常会用到的,后续可能会用到里面的一些库,和opencv有交叉的地方。opencv是从图像中获取数据,opengl是从数据生成图片,进行渲染。
再次编译后,会出下如下错误,这时候我们需要逐个修改路径:修改前和修改后的路径如下图所示(注意: OPENGL中出现的错误不用管,修改了QT中的错误,其他错误自然就好了): 其实在这篇文章中也详细提到了这个,从这一步开始,后面的步骤和这篇文章 Qt配置OpenCV教程,亲测已试过(详细版)大差不差,但是我觉得还是要写完,毕竟每个人的环境可能会有出入。
完了之后,就会发现一切正常了。
最后,点击Generate,生成makefile文件,完成之后,关闭Cmake即可,此时进入之前我们新建的文件夹
D:\Opencv\opencv\Qt_OpenCV_Build
mingw32-make -j 8
mingw32-make install
D:\Opencv\opencv\Qt_OpenCV_Build\install\x64\mingw\bin
这里大家可以测试两个程序:
1:来自B站:QT+OpenCV从零打造美颜软件 | 图像处理入门教程这个讲的比较详细,但是写在博客里面的话比较啰嗦,可以之后再看。
2:基于Qt的OpenCV人脸识别(一)这里用的是第二个。
INCLUDEPATH += D:/Opencv/opencv/Qt_OpenCV_Build/install/include/opencv2 \ #这两个是必加的
D:/Opencv/opencv/Qt_OpenCV_Build/install/include
LIBS += D:/Opencv/opencv/Qt_OpenCV_Build/lib/libopencv_*.a
其中libopencv_*.a表示以libopencv开头,以a结尾的所有静态库文件,由于.a是拓展名,跟在dll后面。 注意反斜杠不要搞错了, \的意思是后面还有内容
可以按ctrl+s或者点击qmake进行构建
首先设置ui界面,用到了两个label和三个pushbutton,label设置了样式表,所以有背景颜色,样式表中加入了如下代码QLabel{background-color:rgb(200,101,102);}
mainwindows.h的代码如下:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //防止报错 'CV_BGR2RGB' was not declared
using namespace cv;
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
QImage Mat2QImage(Mat cvImg);
private slots:
void openCamara(); // 打开摄像头
void readFarme(); // 读取当前帧信息
void closeCamara(); // 关闭摄像头。
void takingPictures(); // 拍照
private:
Ui::MainWindow *ui;
QTimer *timer;
QImage imag;
Mat cap,cap_gray,cap_tmp; //定义一个Mat变量,用于存储每一帧的图像
VideoCapture capture; //声明视频读入类
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
using namespace cv;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(readFarme())); // 时间到,读取当前摄像头信息
connect(ui->open, SIGNAL(clicked()), this, SLOT(openCamara()));
connect(ui->take, SIGNAL(clicked()), this, SLOT(takingPictures()));
connect(ui->close, SIGNAL(clicked()), this, SLOT(closeCamara()));
}
//打开摄像头
void MainWindow::openCamara()
{
capture.open(0); //从摄像头读入视频如果设备只有一个摄像头就传入参数0
qDebug("open");
if (!capture.isOpened()) //先判断是否打开摄像头
{
qDebug("err");
}
timer->start(20); // 开始计时,20ms获取一帧
}
//读取摄像头信息
void MainWindow::readFarme()
{
capture>>cap; //读取当前帧
if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
{
imag = Mat2QImage(cap);
imag = imag.scaled(ui->camera->width(), ui->camera->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
//imshow(name, cap); //若当前帧捕捉成功,显示
ui->camera->setPixmap(QPixmap::fromImage(imag)); // 将图片显示到label上
}
else
qDebug("can not ");
}
// 拍照
void MainWindow::takingPictures()
{
capture>>cap; //读取当前帧
if (!cap.empty()) //判断当前帧是否捕捉成功 **这步很重要
{
imag = Mat2QImage(cap);
imag = imag.scaled(ui->photo->width(), ui->photo->height(),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
//imshow(name, cap); //若当前帧捕捉成功,显示
ui->photo->setPixmap(QPixmap::fromImage(imag)); // 将图片显示到label上
}
else
qDebug("can not ");
}
//关闭摄像头,释放资源,必须释放***
void MainWindow::closeCamara()
{
timer->stop(); // 停止读取数据。
}
// 图片转换(网上抄的)
QImage MainWindow::Mat2QImage(Mat cvImg)
{
QImage qImg;
if(cvImg.channels()==3) //3 channels color image
{
cv::cvtColor(cvImg,cvImg,CV_BGR2RGB);
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols, cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_RGB888);
}
else if(cvImg.channels()==1) //grayscale image
{
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols,cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_Indexed8);
}
else
{
qImg =QImage((const unsigned char*)(cvImg.data),
cvImg.cols,cvImg.rows,
cvImg.cols*cvImg.channels(),
QImage::Format_RGB888);
}
return qImg;
}
MainWindow::~MainWindow()
{
delete ui;
}
补充一个小技巧:shift+r
可以预览ui界面
最后
如果觉得对你有所帮助的话,希望能点赞收藏一波,您的鼓励就是对我最大的支持,谢谢!