人脸识别:
/***********************************************************************************头文件****************************************************************************************/#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_OBJECTpublic: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);}