1.基本概念
基于OpenCV的人脸识别是一个多步骤的过程,通常涉及以下步骤:
-
人脸检测:使用Haar级联或深度学习模型来检测图像中的面部区域。OpenCV提供了预训练的Haar级联分类器,可以用于快速检测。
-
特征提取:一旦检测到人脸,就需要从人脸图像中提取特征。特征提取可以使用多种方法,如LBP(局部二值模式)、HOG(方向梯度直方图)或更先进的深度学习方法。
-
人脸识别:使用特征匹配或机器学习模型来识别检测到的面部。可以使用如支持向量机(SVM)、k-最近邻(k-NN)、神经网络等方法。
-
训练模型:在实际应用中,通常需要收集一些人脸图像来训练识别模型。训练过程中,模型会学习区分不同的人脸。
-
实时识别:在训练完成后,可以使用模型进行实时人脸识别。这可以用于多种应用,如安全监控、身份验证等。
2.项目展示
(1)打开QT,并运行项目,把电脑摄像头对准人脸
(2)输入要录入人的姓名,输入完之后点击录入,录入完之后会有提示
(3)成功录入之后,就可以进行打卡了,把摄像头对准人脸,等待识别,识别成功就签到成功了
(4) 打卡签到成功之后,点击打卡时间就可以查看打卡历史记录。
3.项目开发流程
(1)准备工作
pro文件配置:加载OpenCV文件路径
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-install/install/include/opencv2
LIBS += D:/opencv/opencv3.4-install/install/x86/mingw/lib/libopencv_*.a
头文件支持
#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>
#include <QMessageBox>
#include <QDebug>
#include <QTimerEvent>
#include <QTimer>
#include <QDateTime>
#include <vector>
#include <QFile>
using namespace cv::face;
using namespace cv;
using namespace std;
(2)QT的UI界面
(3)摄像头初始化模块
mainwindow.h添加:
//定义摄像头的初始化
private:
void initVideoCapture();
//定义视频流工具对象属性
private:
VideoCapture vc;
mainwindow.c添加:
//实现摄像头初始化函数
void MainWindow::initVideoCapture(){
//打开摄像头,摄像头标识是0号
//打开摄像头
if(vc.open(0) == false){
//输出内容
qDebug() << "call initVideoCapture open error";
//返回
return;
}else{
//输出内容
qDebug() << "call initVideoCapture open ok";
}
}
(4)级联分类器初始化模块
mainwindow.h添加:
//定义级联分类器对象的初始化
private:
void initCascadeClassifier();
//定义级联分类器对象:人脸识别工作
private:
CascadeClassifier classifier;
mainwindow.c添加:
//实现级联分类器对象的初始化
void MainWindow::initCascadeClassifier(){
//分类:人脸
//分类配置:人脸配置
//人脸配置文件位置:D:/opencv/heads/haarcascade_frontalface_alt2.xml
//通过配置文件haarcascade_frontalface_alt2.xml创建级联分类器对象
classifier = CascadeClassifier(FACETOOL);
//参数1:人脸识别的配置文件
//CascadeClassifier工具类
//CascadeClassifier()工具类的构造器方法
//判断级联分类器对象classifier是否创建成功
if(classifier.empty() == true){
//输出内容
qDebug() << "call initCascadeClassifier classifier error";
return;
}else{
//输出内容
qDebug() << "call initCascadeClassifier classifier ok";
}
}
(5)人脸识别器初始化模块
mainwindow.h添加:
//定义人脸识别器的初始化
private:
void initFaceRecognizer();
//定义人脸识别器的对象的指针变量
Ptr<FaceRecognizer> recognizer;
mainwindow.c添加:
//实现人脸识别器的初始化
void MainWindow::initFaceRecognizer(){
//训练的模型存储的地方:D:/opencv/heads/myface.xml
//访问模型文件,关联模型文件
QFile file("D:/opencv/heads/myface.xml");
//QFile是文件管理工具类
//file是文件管理工具类的对象
//file()构建文件管理工具对象的构造器
//参数:要管理的文件的路径
//判断文件是否存在
if(file.exists() == true){
//输出内容
qDebug() << "call initFaceRecognizer file exist";
//加载模型创建人脸识别器对象
recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/heads/myface.xml");
//FaceRecognizer 人脸识别器工具类的基类
//load()方法是加载模型的方法,创建一个人脸识别器对象
//LBPHFaceRecognizer是人脸识别器的子类
//参数1:模型的路径
//模型文件:xxx.xml
//输出内容
qDebug() << "call initFaceRecognizer load myface.xml";
}else{
//输出内容
qDebug() << "call initFaceRecognizer file not exist";
//创建人脸识别器对象
recognizer = LBPHFaceRecognizer::create();
//create()方法是创建人脸识别器对象的方法
//输出内容
qDebug() << "call initFaceRecognizer LBPHFaceRecognizer create";
}
}
(6)定时器模块
mainwindow.h添加:
//定义定时器标识属性
private:
Mat src;//定义摄像头读取的图像
//声明定时器处理方法(定时器事件触发)
private:
void timerEvent(QTimerEvent *e);
mainwindow.c添加:
//定时器处理方法实现
void MainWindow::timerEvent(QTimerEvent *e){
vc>>src;//读取图像
if(src.empty())//判断是否加载到了图像
return;
flip(src,src,1);//翻转摄像头
//重置图像大小
cv::resize(src,src,Size(600,600));
}
(7)人脸绘制模块
mainwindow.h添加:
private:
Rect ret;//定义有效矩形
private:
void blackSrc();//画有效区域
mainwindow.cpp添加:
void MainWindow::blackSrc()
{
//创建矩形对象
ret = Rect(src.cols/2-150,src.rows/2-150,300,300);
//画白框
rectangle(src,ret,Scalar(255,255,255),2);
//遍历像素点
for(int i=0;i<src.cols;i++)
{
for(int j=0;j<src.rows;j++)
{
//判断是否在有效区域内
if(!ret.contains(Point(i,j)))
{
//修改像素点的值
src.at<Vec3b>(j,i)[0] = saturate_cast<uchar>(src.at<Vec3b>(j,i)[0]-50);//蓝色
src.at<Vec3b>(j,i)[1] = saturate_cast<uchar>(src.at<Vec3b>(j,i)[1]-50);//绿色
src.at<Vec3b>(j,i)[2] = saturate_cast<uchar>(src.at<Vec3b>(j,i)[2]-50);//红色
}
}
}
}
补充代码:
//定时器处理方法实现
void MainWindow::timerEvent(QTimerEvent *e){
vc>>src;//读取图像
if(src.empty())//判断是否加载到了图像
return;
flip(src,src,1);//翻转摄像头
//重置图像大小
cv::resize(src,src,Size(600,600));
blackSrc();
}
(8)人脸识别模块
mainwindow.h添加:
//定义人脸查找方法
private:
void findFace();
//定义属性存储摄像头数据
private:
Mat mid;//定义图像对象
//定义属性存储摄像头人脸的位置关系
private:
vector<Rect> faces;
mainwindow.c添加:
void MainWindow::findFace()
{
//创建灰度图对象
Mat gray;
//截取有效区域内图像
mid = src(ret);
//色彩空间转换
cvtColor(mid,gray,CV_BGR2GRAY);
//检测函数来获取人脸矩形
classifier.detectMultiScale(gray,faces);
//给人脸矩形画红框
if(faces.size()>0)//判断是否找到人脸
rectangle(mid,faces[0],Scalar(0,0,255),2);
}
补充代码:
//定时器处理方法实现
void MainWindow::timerEvent(QTimerEvent *e){
vc>>src;//读取图像
if(src.empty())//判断是否加载到了图像
return;
flip(src,src,1);//翻转摄像头
//重置图像大小
cv::resize(src,src,Size(600,600));
blackSrc();
findFace();
}
(9)人脸显示模块
mainwindow.h添加:
//定义人脸显示函数
private:
void showImage();//显示图像
mainwindow.cpp添加:
//实现人脸显示功能
void MainWindow::showImage()
{
//qt : rgb opencv :bgr
Mat rgb;
//色彩空间转换
cvtColor(src,rgb,CV_BGR2RGB);
//Mat->QImage
QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
//QImage->QPixmap
QPixmap p = QPixmap::fromImage(img);
//显示图像
ui->label_video->setPixmap(p);
}
补充代码:
//定时器处理方法实现
void MainWindow::timerEvent(QTimerEvent *e){
vc>>src;//读取图像
if(src.empty())//判断是否加载到了图像
return;
flip(src,src,1);//翻转摄像头
blackSrc();
findFace();
showImage();
}
(10)按键的槽函数实现
mainwindow.h添加:
//定义自定义定时器
QTimer studyTimer;
mainwindow.cpp添加:
void MainWindow::on_pushButton_insert_clicked()
{
studyTimer.start(1000);//开启机械学习定时器,每一秒执行一次
}
//自定义定时器的连接函数
connect(&studyTimer,SIGNAL(timeout()),this,SLOT(slot_luru()));
(11)机器学习模块
mainwindow.h添加:
//定义人脸查找方法
private:
void slot_luru();
private:
//定义属性存储摄像头人脸face内容
vector<Mat> studyFaces;
//定义属性存储摄像头人脸对应的id
int id;
bool isLuru;//定义学习状态变量
mainwindow.c添加:
//实现机器学习功能
void MainWindow::slot_luru()
{
if(faces.size()<=0)
return;
if(studyFace.size() == 10)
{
studyTimer.stop();//停止机械学习
vector<int> labels;//保存标签的容器
//从ui端获取名字
QString name = ui->lineEdit_name->text();
//更新人员表
ManagerFactory::getIns()->user->insertUser(name);
//获取当前的用户id
id = ManagerFactory::getIns()->user->selectId();
//往容器中插入标签 插入10个一样的标签
labels.insert(labels.begin(),10,id);
//学习并且更新模型文件
recognizer->update(studyFace,labels);
recognizer->save("face.xml");//保存模型文件
//提示:录入成功 #include <QMessageBox>
QMessageBox::information(this,"提示","恭喜,录入人员成功");
ui->lineEdit_name->clear();//清空单行输入框
studyFace.clear();//清空容器
isLuru = false;//推出学习状态
}
else
{
Mat face = mid(faces[0]);//截取人脸矩形的部分
//色彩空间转换
cvtColor(face,face,CV_BGR2GRAY);
//统一尺寸
cv::resize(face,face,Size(100,100));
//存放在容器
studyFace.push_back(face);
qDebug()<<studyFace.size();
}
}
(12)人脸预测模块
mainwindow.h添加:
//对应方法完成预测功能
private:
void checkFace();
mainwindow.cpp添加:
void MainWindow::checkFace()
{
//找不到人脸 机械学习状态 人脸识别器为空
if(faces.size()<=0 || isLuru || recognizer->empty())
{
return;
}
//1.截取人脸区域
Mat face = src(faces[0]);
//色彩空间转换
cvtColor(face,face,CV_BGR2GRAY);
//与机械学习时的尺寸同一
cv::resize(face,face,Size(100,100));
//给标签 和可信度 设定初始值
int label = -1;
double confidence =0;
//预测人脸
recognizer->predict(face,label,confidence);
qDebug()<<confidence;
//提示打卡信息
if(label != -1 && confidence < 150)
{
//获取下名字
QString name = ManagerFactory::getIns()->user->selectName(label);
//拼接显示标题
QString str = name + "已签到";
//用消息提示框提示签到成功
QMessageBox::warning(this,str,QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
//往时间记录表中插入数据
ManagerFactory::getIns()->time->insertTime(name);
}
}
结语
以上就是人脸识别的主要内容,本次代码分享到此结束,有需要源码的请联系我VX:gfx2503654393 。最后的最后,还请大家点点赞,点点关注,谢谢大家!