QT人脸识别知识

**机器学习的作用:**根据提供的图片模型通过算法生成数据模型,从而在其它图片中查找相关的目 标。

**级联分类器:**是用来人脸识别。 在判断之前,我们要先进行学习,生成人脸的模型以便后续识别使用。

**人脸识别器:**判断是谁的面部。 FaceRecognizer类是opencv提供的人脸识别器基类,LBPHFaceRecognizer是根据LBPH算法实现的识别器类,其中LBPHFaceRecognizer识别器支持在原有模型基础上继续学习(模型数据可以累计)。

创建LBPHFaceRecognizer识别器对象

cpp 复制代码
 所需的头文件:#include 、using namespace cv::face;
 创建空的人脸识别器对象:Ptr<FaceRecognizer> recognizer =
 LBPHFaceRecognizer::create();
 ​
 根据已有的模型创建人脸识别器对象,在创建人脸识别器的时候,需要一个已经学习好的模型文件:
 Ptr<FaceRecognizer> recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("模型文
 件.xml");

机器学习并更新模型

cpp 复制代码
 容器:容器中装了n张人脸Mat对象,先采集脸,装到容器中,存储标签,人的身份证,每一张脸
 给一个编号:1 张三脸 2 李四脸 3 王五脸。
 功能函数1:void update(InputArrayOfArray src,InputArray labels)//机器学习并更新模型
 功能函数2:void train(InputArrayOfArrays src,InputArray labels);//只是学习,不更新
 //参数1src:图片模型数组 vector<Mat>
 //参数2labels:标签数组,每个模型识别后的标签vector<int>

保存模型

cpp 复制代码
 功能函数:void save(const String& filename);//参数1:模型文件的名字
 例如:
 recognizer->update(study_faces,study_label);//学习
 recognizer->save("face.xml");//将学习的成果,保存到face.xml模型文件中,生成模型:
 study_faces.clear();、study_labels.clear();

预测目标

cpp 复制代码
 判断这个人脸到底是谁。
 功能函数:
 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。
 

设置可信度

cpp 复制代码
 功能函数:void setThreshold(double val);
 //参数1:预测可信度极值,预测可信度超出极值则预测失败。

实例:

头文件

cpp 复制代码
#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();


private slots:
    void on_openCameraBtn_clicked();


    void on_closeCameraBtn_clicked();


    void on_inputFaceBtn_clicked();


private:
    Ui::Widget *ui;
    /***********************第一模块:关于摄像头的相关组件**********************/
    VideoCapture v;              //视频流对象


    Mat src;                     //原图像
    Mat rgb;                     //存放rgb图像,因为qt能识别的图像色彩空间为rgb
    Mat gray;                    //灰度图
    Mat dst;                     //均衡化图像


    CascadeClassifier c;         //级联分类器
    vector<Rect> faces;             //存储人脸矩形区域的容器
    int cameraId;                //摄像头的定时器
    void timerEvent(QTimerEvent *event);   //定时器事件处理函数


    /**********************第二模块:录入人脸的相关组件************************/
    Ptr<FaceRecognizer> recognizer;          //人脸识别器
    vector<Mat> study_face;                  //要录入的人脸容器
    vector<int> study_lab;                   //要录入的人脸的标签
    int studyId;                             //人脸录入的定时器
    int flag;                                //标识是否正在录入人脸
    int count;                                //记录学习的次数


    /**********************第三模块:人脸检测相关组件*************************/
    int checkId;                  //人脸检测的定时器




};


#endif // WIDGET_H

源文件:

cpp 复制代码
#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<LBPHFaceRecognizer>("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; i<faces.size(); i++)
        {
            rectangle(rgb, faces[i], Scalar(255,0,0), 2);
        }


        //9、使用rgb图像,将Mat图,构造出一个qt能识别的图像
        QImage img(rgb.data, rgb.cols, rgb.rows, rgb.cols*rgb.channels(), QImage::Format_RGB888);
        //功能:通过其他图像构造出一个QImage图像
        //参数1:其他图像的数据
        //参数2:图像的宽度
        //参数3:图像的高度
        //参数4:每一行的字节数
        //参数5:图像格式,24位图,每一种颜色使用8位表示


        //10、将图像展示到lab中
        ui->cameraLab->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 = "<<lab<<"   conf = "<<conf;


                //对人脸识别后的结果进行判断
                if(lab != -1)
                {
                    ui->loginBtn->setEnabled(true);
                }


            }
        }


    }


}


//录入人脸按钮对应的槽函数
void Widget::on_inputFaceBtn_clicked()
{
    //启动人脸录入的定时器
    qDebug()<<"开始进行人脸录入...";


    studyId = this->startTimer(60);


    //将按钮设置成不可用状态
    ui->inputFaceBtn->setEnabled(false);
    //将flag设置成1,表示正在录入人脸,不要进行人脸检测了
    flag = 1;
    count = 0;           //清空计数器
}
相关推荐
玉红77718 分钟前
R语言的数据类型
开发语言·后端·golang
夜斗(dou)21 分钟前
node.js文件压缩包解析,反馈解析进度,解析后的文件字节正常
开发语言·javascript·node.js
觅远23 分钟前
python+PyMuPDF库:(一)创建pdf文件及内容读取和写入
开发语言·python·pdf
神雕杨1 小时前
node js 过滤空白行
开发语言·前端·javascript
lvbu_2024war011 小时前
MATLAB语言的网络编程
开发语言·后端·golang
single5942 小时前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
游客5202 小时前
自动化办公-合并多个excel
开发语言·python·自动化·excel
Cshaosun2 小时前
js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)
开发语言·javascript·es6
凡人的AI工具箱2 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
SomeB1oody2 小时前
【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
开发语言·后端·rust