1、配置文件.pro
#-------------------------------------------------
#
# Project created by QtCreator 2023-09-05T19:00:36
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = 01_face
TEMPLATE = app
SOURCES += main.cpp\
widget.cpp
HEADERS += widget.h
FORMS += widget.ui
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv2
LIBS += D:/opencv/opencv3.4-qt-intall/install/x86/mingw/lib/libopencv_*.a
2、头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include<opencv2/face.hpp>
#include <vector>
#include <map>
#include <QMessageBox>
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
#include <QTimerEvent>
#include<QtSerialPort/QtSerialPort>
#include<QtSerialPort/QSerialPortInfo>
using namespace cv;
using namespace cv::face;
using namespace std;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void timerEvent(QTimerEvent *event); //定时器事件处理函数
private slots:
void on_open_camera_Btn_clicked();
void on_close_camera_Btn_clicked();
void on_input_face_Btn_clicked();
private:
Ui::Widget *ui;
/************************第一模块:关于摄像头的组件***********************/
VideoCapture v; //定义一个视频流对象
Mat src; //原图像
Mat rgb; //由于qt不识别grb图像,所以需要转化为rgb图像
Mat gray; //灰度图
Mat dst; //均衡化图像
CascadeClassifier c; //级联分类器,用来获取人像的矩形框
vector<Rect> faces; //定义一个存储人像矩形的容器
int camera_timer_id; //定时器
/************************第二模块:录入人脸的组件***********************/
Ptr<FaceRecognizer> recognizer; //人脸识别器
vector<Mat> study_face; //要录入的人脸容器
vector<int> Study_lab; //要录入的人脸标签
int input_timer_id; //录入人脸的定时器
int flag; //判断是否正在录入中
int count; //记录收集到的人脸的次数
/************************第三模块:人脸检测的组件***********************/
int check_timer_id; //定义一个人脸检测的定时器
};
#endif // WIDGET_H
3、源文件
main.app
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
int face_count = 1; //录入对应的标签号
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//打开摄像头
if(!v.open(0))
{
QMessageBox::information(this, "提示", "摄像头打开失败");
return;
}
//将级联分类器加载进来
if(!c.load("D:/opencv/resource/haarcascade_frontalface_alt2.xml"))
{
QMessageBox::information(this, "提示", "练级分类器加载失败");
return;
}
//配置人脸识别器
QFile file("D:/opencv/resource/Face.xml");
//判断是否存在,存在将其下载下来,不存在创建人脸模型
if(file.exists())
{
//存在人脸模型,下载进来
recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/resource/Face.xml");
}
else
{
//不存在,创建LBPHFaceRecognizer::create()
recognizer = LBPHFaceRecognizer::create();
}
//启动人脸检测定时器
check_timer_id = startTimer(3000);
flag = 0;
//设置可信度
recognizer->setThreshold(100);
}
Widget::~Widget()
{
delete ui;
}
//打开摄像头按钮的槽函数
void Widget::on_open_camera_Btn_clicked()
{
//开启定时器
camera_timer_id = this->startTimer(20);
}
void Widget::on_close_camera_Btn_clicked()
{
//关闭定时器
this->killTimer(camera_timer_id);
}
//定时器事件的函数
void Widget::timerEvent(QTimerEvent *event)
{
//判断是否是打开摄像头定时器到位
if(event->timerId() == camera_timer_id)
{
//获取图像
//函数原型:virtual bool read(OutputArray image);
//参数:存储读取到的图像容器
//成功返回真,失败/读取完毕返回假
v.read(src);
//翻转图像
//函数原型:oid flip(InputArray src, OutputArray dst, int flipCode);
flip(src, src, 1);
//将图像转为rgb模式
cvtColor(src, rgb, CV_BGR2RGB);
//重新设置图像大小
cv::resize(rgb, rgb, Size(300,300));
//灰度化处理
cvtColor(rgb, gray, CV_RGB2GRAY);
//均衡化处理
equalizeHist(gray, dst);
//使用级联分类器获取人脸图像的矩形框,并存入参数2中(人像矩形框容器中)
//函数原型:void detectMultiScale( InputArray image,
// CV_OUT std::vector<Rect>& objects,
// double scaleFactor = 1.1,
// int minNeighbors = 3, int flags = 0,
// Size minSize = Size(),
// Size maxSize = Size() );
c.detectMultiScale(dst, faces);
//将矩形框绘制到rgb图像中去
for(int i=0; i<faces.size(); i++)
{
//使用全局函数rectangle函数,进行绘制
rectangle(rgb, faces[i], Scalar(255, 0, 0), 1);
}
//将图像显示到ui界面上,ui界面的图像为QPixmap
//需要将rgb图转为QImage的图像,再转为QPIXmap
QImage img(rgb.data, rgb.cols, rgb.rows, rgb.cols*rgb.channels(), QImage::Format_RGB888);
//功能:通过其他图像构造一个QImage图像
//参数1:其他图像的数据
//参数2:图像的宽度(列)
//参数3:图像的高度(4)
//参数4:每一行的字节数(列*通道)
//参数5:图像格式,24位图,每一中颜色使用1字节8位表示
//将其设置到ui界面的组件上
ui->camera_Lab->setPixmap(QPixmap::fromImage(img)); //QPixmap::fromImage(img); 将QImage图像转为QPixmap图像
}
//判断是否是录入人脸定时器到位
if(input_timer_id == event->timerId())
{
qDebug() << "正在录入....";
//判断ui界面是否有矩形框
if(faces.empty()) return;
//判断人脸识别器是否存在
if(recognizer.empty()) return;
//获取矩形框中的图像
Mat face = src(faces[0]);
//重新设置大小
cv::resize(face, face, Size(100, 100));
//灰度化处理
cvtColor(face, face, CV_BGR2GRAY);
//均衡化处理
equalizeHist(face, face);
qDebug() << face_count;
//将图像放入学习容器中
study_face.push_back(face);
Study_lab.push_back(face_count);
count++;
//当收集50张后更新学习模型
if(50 == count)
{
qDebug() << "hahhah";
//将图像模型转为数据模型
//函数原型:virtual void update(InputArrayOfArrays src, InputArray labels);
//参数1:要进行更新的人脸图像容器
//参数2:要进行封信的人脸标签容器
recognizer->update(study_face, Study_lab);
//将数据模型存入到本地磁盘中去
recognizer->save("D:/opencv/resource/Face.xml");
QMessageBox::information(this, "提示", "人脸录入成功");
flag = 0;
count = 0;
killTimer(input_timer_id);
study_face.clear();
Study_lab.clear();
face_count++;
}
}
//判断是否是人脸检测定时器到位
if(event->timerId() == check_timer_id)
{
if(0 == flag)
{
QFile file("D:/opencv/resource/Face.xml");
//判断文件是否存在
if(file.exists())
{
//判断ui->界面是否有矩形框和人脸识别器是否有
if(faces.empty() || recognizer.empty()) return;
//到此说明开始检测
//获取ui界面上的矩形框中的图像
Mat face = src(faces[0]);
//重新设置图像大小, 与录入人脸时的大小一致
cv::resize(face, face, Size(100, 100));
//灰度化处理
cvtColor(face, face, CV_BGR2GRAY);
//均衡化处理
equalizeHist(face, face);
//定义记录,检测后的结果
int lab = -1;
double conf = 0.0;
//将人脸进行检测
recognizer->predict(face, lab, conf);
//判断是否匹配
if(lab != -1)
{
qDebug() <<"匹配成功";
}
qDebug() << lab;
}
}
}
}
//录入人脸对应的参函数
void Widget::on_input_face_Btn_clicked()
{
//启动定时器
input_timer_id = startTimer(60);
//将flag设置为1, 表明正在录入
flag = 1;
count = 0;
}
4、ui界面