人脸识别:
/***********************************************************************************头文件****************************************************************************************/
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QWidget>
#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();
private slots:
void on_opencameraBtn_clicked();
void on_closecameraBtn_clicked();
void on_faceStudyBtn_clicked();
private:
Ui::Widget *ui;
/***********************第一模块:摄像头展示相关成员**************************/
//定义视频流对象
VideoCapture v;
//定义图像容器
Mat src; //存储原色图
Mat gray; //存储灰度图
Mat dst; //存储均衡化图像
Mat rgb; //存储转化成的rgb图
//定义级联分类器类
CascadeClassifier c; //该类用于使用模型进行相关区域分类工作
//定义存储人脸矩形框的数组
vector<Rect>faces;
//定义展示摄像头的定时器
int camera_timer_id;
//重写定时器事件处理函数
void timerEvent(QTimerEvent *e);
/***********************第二模块:人脸录入相关成员****************************/
Ptr<LBPHFaceRecognizer> recognizer; //人脸识别的指针
vector<Mat>study_faces; //训练人脸的人脸容器
vector<int>study_lab; //记录要存储人脸的id标签
int count; //记录机器学习的次数
int flag; //记录是否正在录入人脸
int study_timer_id; //人脸录入的定时器
/**********************第三模块:人脸检测*************************************/
int check_timer_id;
};
#endif // WIDGET_H
/*******************************************************************源文件***************************************************************************************************************************/
#include "widget.h"
#include "ui_widget.h"
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(NULL,"","级联分类器加载失败");
return ;
}
//给人脸识别区空间
QFile file("D:\\opencv\\resource\\myface.xml");
//判断人脸模型是否存在
if(file.exists())
{
//判断人脸模型是否存在
recognizer=FaceRecognizer::load<LBPHFaceRecognizer>("D:\\opencv\\resource\\myface.xml");
}else
{
//此时表明人脸模型不存在,需要创建出一个人脸模型
recognizer=LBPHFaceRecognizer::create(); //调用静态成员函数,创建出一个人脸模型
}
//初始时将登录按钮设置成不可用状态,当人脸识别成功后,该按钮设置层可用状态
ui->loginBtn->setEnabled(false);
//启动人脸预测的定时器
check_timer_id=startTimer(3000);
//程序运行时应处于检测过程而不是学习过程
flag=1;
//设置可信度
recognizer->setThreshold(100); //后期识别后,如果可信度低于100,则说明识别成功
}
Widget::~Widget()
{
delete ui;
}
//定时器事件处理函数
void Widget::timerEvent(QTimerEvent *e)
{
if(e->timerId()==camera_timer_id) //说明展示摄像头的定时器到位,处理摄像头的功能
{
//从视频流中读取一张图像放入src中
v.read (src);
//镜像处理
flip(src, src, 1);
//色彩空间转化,将bgr图转化为rgb图
cvtColor(src,rgb,CV_BGR2RGB);
//将图像重新设置大小
cv::resize(rgb,rgb,Size(300,300));
//灰度处理
cvtColor(rgb,gray,CV_BGR2GRAY);
//均衡化处理
equalizeHist(gray,dst);
//获得人脸矩形框
c.detectMultiScale(dst,faces);
//将人脸矩形区域绘制到rgb图上
for(int i=0;i<faces.size();i++)
{
rectangle(rgb,faces[i],Scalar(255,0,0),2);
}
//使用rgb图构造出一个qt能够识别的图像
//QImage (const uchar *data,int width,int height,int bytesPerLine,Format format;
//功能:构造一个QImage图
//参数1:其他图像的数据域
//参数2:其他图像的宽度
//参数3:其他图像的高度
//参数4:一行内的字节数
//参数5:图像格式
QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
//在ui界面中展示构造出来的图像
ui->cameraLab->setPixmap(QPixmap::fromImage(img));
}
//判断是否是人脸录入定时器到位
if(e->timerId()==study_timer_id)
{
qDebug()<<"正在录入,请稍后...";
//获取ui界面中的矩形框框起来的人脸区域
Mat face; //要存储的人脸
//判断人脸矩形框是否存在
if(faces.empty())
return ; //如果ui界面上人脸矩形框不存在,则直接结束
//从摄像头原图中截取一个矩形框大小的图像放到face变量中
face=src(faces[0]);
//将该脸进行重新设置大小
cv::resize(face,face,Size(50,50));
//色彩空间转换
cvtColor(face,face,CV_BGR2GRAY);
//均衡化处理
equalizeHist(face,face);
//此时,要存储的脸已经准备好了,需要使用人脸识别器进行更新模型操作
//将刚学习的这张脸放入学习容器中
study_faces.push_back(face);
study_lab.push_back(1);
count++; //表明己经学习了一张人脸
if(count==50) //需要学习50次,完成人脸模型的配置
{
recognizer->update(study_faces,study_lab);//完成人脸模型的更新,将图像模型转化为数据模型
//将刚刚生成的人脸数据模型,保存到本地磁盘文件中
recognizer->save("D:\\opencv\\resource\\myface.xml");
//殿后工作
QMessageBox::information(this,"","录入成功");
flag=1; //表明可以进行人脸检测工作
ui->faceStudyBtn->setEnabled(true);//按钮设置成可用状态
study_faces.clear();
study_lab.clear(); //清空两个容器
count=0; //清空计数器,以便下次使用
killTimer(study_timer_id);//关闭人脸录入的定时器
}
}
//判断是否是人脸识别定时器到位
if(e->timerId()==check_timer_id)
{
//判断是否可以进行检测
if(flag==1)
{
qDebug()<<"正在寻找...";
//找到人脸模型
QFile file("D:\\opencv\\resource\\myface.xml");
if(file.exists()) //在人脸模型存在的基础上进行识别
{
//继续判断当前摄像头中是否有人脸存在
if(faces.empty()||recognizer.empty())
return; //表明没有人脸或人脸识别器不存在
//开始进行人脸识别工作
//1、获取摄像头中的人脸区域
Mat face=src(faces[0]);
//2.重新设置大小,为存储时的大小
cv::resize(face,face,Size(50,50));
//3.灰度处理和均衡化处理
cvtColor(face,face,CV_BGR2GRAY);
equalizeHist(face,face);
//定义变量存储人脸预测后的结果
int lab=-1; //预测后的人脸编号
double conf=0.0; //预测后的人脸可信度
//5、进行人脸预测工作
//函数原型: void predict (InputArray src,cv_our int &label,cv_our double &confidence) const;
//功能:对给定的图像进行预测工作
//参数1:要预测的图像
//参数2:预测后的该图像的编号,如果识别失败,则编号保持之前的不变,如果预测成功,则将该图像对应的编号返回
//参数3:人脸识别后的可信度
recognizer->predict(face,lab,conf);
qDebug()<<"lab="<<lab<<" conf="<<conf;
//对人脸识别后的数据进行判断
if(lab!=-1)
{
//说明人脸识别成功
ui->loginBtn->setEnabled(true);
}
}
}
}
}
//打开摄像头按钮对应的槽函数
void Widget::on_opencameraBtn_clicked()
{
//启动打开摄像头的定时器
camera_timer_id=startTimer(20);
}
//关闭摄像头按钮对应的槽函数
void Widget::on_closecameraBtn_clicked()
{
//关闭摄像头的定时器
killTimer(camera_timer_id);
}
//录入人脸按钮对应的槽函数
void Widget::on_faceStudyBtn_clicked()
{
qDebug()<<"开始录入人脸,请正视摄像头...";
flag=0; //0表示正在录入人脸,不要进行检测工作
count=0; //将学习次数清零
//启动录入人脸的定时器
study_timer_id=startTimer(50); //每隔50毫秒学习一次
//将录入按钮设置成不可用状态
ui->faceStudyBtn->setEnabled(false);
}