机器学习的作用:根据提供的图片模型通过算法生成数据模型,从而在其它图片中查找相关的目 标。
级联分类器:是用来人脸识别。 在判断之前,我们要先进行学习,生成人脸的模型以便后续识别使用。
人脸识别器:判断是谁的面部。 FaceRecognizer类是opencv提供的人脸识别器基类,LBPHFaceRecognizer是根据LBPH算法实现的识别器类,其中LBPHFaceRecognizer识别器支持在原有模型基础上继续学习(模型数据可以累计)。
创建LBPHFaceRecognizer识别器对象
所需的头文件:#include 、using namespace cv::face;
创建空的人脸识别器对象:Ptr recognizer =
LBPHFaceRecognizer::create();
根据已有的模型创建人脸识别器对象,在创建人脸识别器的时候,需要一个已经学习好的模型文件:
Ptr recognizer = FaceRecognizer::load("模型文
件.xml");
机器学习并更新模型
容器:容器中装了n张人脸Mat对象,先采集脸,装到容器中,存储标签,人的身份证,每一张脸
给一个编号:1 张三脸 2 李四脸 3 王五脸。
功能函数1:void update(InputArrayOfArray src,InputArray labels)//机器学习并更新模型
功能函数2:void train(InputArrayOfArrays src,InputArray labels);//只是学习,不更新
//参数1src:图片模型数组 vector
//参数2labels:标签数组,每个模型识别后的标签vector
保存模型
功能函数:void save(const String& filename);//参数1:模型文件的名字
例如:
recognizer->update(study_faces,study_label);//学习
recognizer->save("face.xml");//将学习的成果,保存到face.xml模型文件中,生成模型:
study_faces.clear();、study_labels.clear();
预测目标
判断这个人脸到底是谁。
功能函数:
void predict(InputArray src, int &label, double &confidence)
//参数1:预测图形 Mat src
//参数2::预测后的标签,学习时对应的标签
//参数3:预测出结果的可信度,数值越小可信度越高
例如:
int label = -1;//预测后的标签,学习时对应的标签
double confidence = 0;//可信度
Mat face = frame(faces[0]);//人脸区域
cvtColor(face,face,CV_BGR2GRAY);//更改色彩空间
cv::resize(face,face,Size(90,90));//设置人脸的大小
recognizer->predict(face,label,confidence); //预测,相当于识别人脸,预测出人脸是谁的
面部,label的值就那张脸对应的标签,如果预测不到,label的值是-1。
设置可信度
功能函数:void setThreshold(double val);
//参数1:预测可信度极值,预测可信度超出极值则预测失败。
实例:
头文件
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
#include
#include
#include
源文件:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//将登录按钮设置成不可用状态
ui->loginBtn->setEnabled(false);
//启动摄像头
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/myFace.xml");
//判断文件是否存在,如果存在,则直接下载,如果不存在,则创建一个人脸识别器
if(file.exists())
{
//人脸模型存在,直接下载即可
recognizer = FaceRecognizer::load("D:/opencv/resource/myFace.xml");
}else
{
//人脸模型不存在,需要进行创建
recognizer = LBPHFaceRecognizer::create();
}
//启动人脸检测的定时器
checkId = this->startTimer(3000);
//设置人脸识别的可信度
recognizer->setThreshold(100);
flag = 0; //表明开始时就处于检测
}
Widget::~Widget()
{
delete ui;
}
//打开摄像头按钮对应的槽函数
void Widget::on_openCameraBtn_clicked()
{
//启动定时器
cameraId = this->startTimer(20);
ui->cameraLab->show();
}
//关闭摄像头
void Widget::on_closeCameraBtn_clicked()
{
//关闭定时器
this->killTimer(cameraId);
ui->cameraLab->hide();
}
//定时器事件处理函数
void Widget::timerEvent(QTimerEvent *event)
{
//判断是哪个定时器到位
if(event->timerId() == cameraId)
{
//1、从摄像头中读取一张图像
v.read(src); //得到原图
//2、将图像翻转
flip(src, src, 1);
//3、将src的bgr图像转换为rgb图像
cvtColor(src, rgb, CV_BGR2RGB);
//4、重新设置大小
cv::resize(rgb, rgb, Size(300,300));
//5、灰度处理
cvtColor(rgb, gray, CV_RGB2GRAY);
//6、均衡化处理
equalizeHist(gray, dst);
//7、使用级联分类器获取人脸矩形区域
c.detectMultiScale(dst, faces);
//8、将矩形框绘制到rgb图像上
for(int i=0; icameraLab->setPixmap(QPixmap::fromImage(img));
}
//判断是否是人脸录入定时器到位
if(event->timerId() == studyId)
{
//判断ui界面是否有矩形框
if(faces.empty())return;
//判断人脸识别器是否存在
if(recognizer.empty()) return;
//提示正在录入人脸
qDebug()<<"正在录入,请稍后...";
//获取ui界面中矩形框框起来的人脸区域
Mat face = src(faces[0]);
//将该图像进行重新设置大小
cv::resize(face,face,Size(100,100));
//灰度处理
cvtColor(face,face,CV_BGR2GRAY);
//均衡化处理
equalizeHist(face,face);
//将人脸放入学习容器中
study_face.push_back(face);
study_lab.push_back(1);
count++; //表明完成一次人脸的存放
if(count == 50) //已经收集50张人脸进行学习
{
count = 0; //以便于下一次录入
//更新人脸模型,将图像模型转换为数据模型
//函数原型:void update(InputArrayOfArrays src, InputArray labels);
//参数1:要进行更新的人脸数组
//参数2:要跟新的人脸标签数组
//返回值:无
recognizer->update(study_face, study_lab);
//将数据模型保存到本地磁盘中
recognizer->save("D:/opencv/resource/myFace.xml");
//殿后工作
study_face.clear(); //清空人脸数组
study_lab.clear(); //清空标签数组
flag = 0; //表明录入已经结束,可以进行人脸检测了
ui->inputFaceBtn->setEnabled(true); //按钮设置成可用状态
this->killTimer(studyId); //关闭人脸录入的定时器
QMessageBox::information(this,"成功","人脸录入成功");
}
}
//判断是否是人脸检测的定时器到位
if(event->timerId() == checkId)
{
qDebug()<<"正在检测...";
//判断是否处于检测
if(flag == 0)
{
QFile file("D:/opencv/resource/myFace.xml");
if(file.exists()) //表明人脸模型存在的基础上进行识别
{
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);
qDebug()<<"lab = "<startTimer(60);
//将按钮设置成不可用状态
ui->inputFaceBtn->setEnabled(false);
//将flag设置成1,表示正在录入人脸,不要进行人脸检测了
flag = 1;
count = 0; //清空计数器
}