QT实现人脸识别
Face.pro文件:
QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsCONFIG += c++11# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0SOURCES += \main.cpp \widget.cppHEADERS += \widget.hFORMS += \widget.uiINCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv
INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv2
LIBS += D:/opencv/opencv3.4-qt-intall/install/x86/mingw/lib/libopencv_*.a# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
widget.h文件:
#ifndef WIDGET_H
#define WIDGET_H#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;QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private slots:void on_openBtn_clicked();void on_closeBtn_clicked();void on_faceBtn_clicked();private:Ui::Widget *ui;//=========摄像头相关成员的设置=========VideoCapture v; //摄像头容器Mat src; //存放 原图 的容器Mat gray; //存放 灰度图 的容器Mat dst; //存放 直方图 的容器Mat rgb; //存放 rgb图 的容器CascadeClassifier c; //定义一个级联分类器容器vector<Rect> faces; // 定义一个数组存放人脸矩形框int camera_id; //打开摄像头的定时器idvoid timerEvent(QTimerEvent *e); //定时器事件 重写函数事件声明//=========人脸录入相关成员的设置=========Ptr<LBPHFaceRecognizer> recognizer; //人脸 识别器指针vector<Mat> study_faces; //定义一个存放录入人脸的数组vector<int> study_lables; //定义一个存放人脸对应的标签数组int count; //记录录入人脸的次数int flag; //用来区别是人脸录入还是人脸识别int face_id; // 人脸录入定时器id//=========人脸检测相关成员的设置=========int check_id; //};
#endif // WIDGET_H
widget.cpp文件:
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->weChatBtn->setEnabled(false);//打开系统摄像头if(!v.open(0)){QMessageBox::information(this, "", "打开系统摄像头失败!");return;}//配置 级联分类器if(!c.load("D:\\opencv\\image\\haarcascade_frontalface_alt.xml")){QMessageBox::information(this, "", "配置级联分类器失败!");return;}//判断是否录入过人脸QFile file("D:\\opencv\\image\\my_face.xml");//判断文件是否存在if(file.exists()){//表示之前录入过人脸 则下载文件recognizer = LBPHFaceRecognizer::load<LBPHFaceRecognizer>("D:\\opencv\\image\\my_face.xml");}else {//表示之前没有录入过人脸recognizer = LBPHFaceRecognizer::create();}//启动一个人脸检测定时器check_id = startTimer(3000);flag = 1; //可以人脸检测recognizer->setThreshold(100);}Widget::~Widget()
{delete ui;
}//打开摄像头按钮对应的 槽函数
void Widget::on_openBtn_clicked()
{//启动一个定时器camera_id = startTimer(30);
}//定时器重写的功能函数
void Widget::timerEvent(QTimerEvent *e)
{//判断是否是 摄像头定时器 超时if(e->timerId() == camera_id){//读取系统摄像头中的图像v.read(src);//图像反转flip(src, src, 1);//将 bgr 转换成 rgbcvtColor(src, rgb, CV_BGR2RGB);//将图像重新设置大小 适应labcv::resize(rgb, rgb, Size(301,251));//灰度处理cvtColor(rgb, gray, CV_RGB2GRAY);//均衡化处理equalizeHist(gray, dst);//锁定人脸矩形框位置c.detectMultiScale(dst, faces);//将矩形框绘制到人脸上for(uint i=0; i<faces.size(); i++){rectangle(rgb, faces[i], Scalar(255,0,0),2);}//将图像放入 lab 中QImage img(rgb.data, rgb.cols, rgb.rows, rgb.cols*rgb.channels(), QImage::Format_RGB888);ui->label->setPixmap(QPixmap::fromImage(img));}//判断是否是 人脸录入定时器 超时if(e->timerId() == face_id){if(0 == flag){qDebug() << "人脸录入中,请正视摄像头!";Mat face = src(faces[0]); //将摄像头当前的一帧图像上的一个人脸给face//灰度处理cvtColor(face, face, CV_BGR2GRAY);//均衡化处理equalizeHist(face, face);//将人脸放入数组中study_faces.push_back(face);study_lables.push_back(1);count++;if(50 == count){//将图像模型转换成数据模型recognizer->update(study_faces, study_lables);recognizer->save("D:\\opencv\\image\\my_face.xml");QMessageBox::information(this, "", "录入人脸成功!");//关闭定时器killTimer(face_id);flag = 1; //表示可以人脸识别study_faces.clear(); //将存放人脸数组清空,方便下次录入study_lables.clear();}}}//判断是否是 人脸检测定时器 超时if(e->timerId() == check_id){if(1 == flag){QFile file("D:\\opencv\\image\\my_face.xml");if(file.exists()){if(recognizer.empty() || faces.empty()){return;}Mat face = src(faces[0]);//灰度处理cvtColor(face, face, CV_BGR2GRAY);//equalizeHist(face, face);int lab = -1;double cof = 0.0;recognizer->predict(face, lab, cof);//根据 lab 判断是否识别成功if(lab != -1){QMessageBox::information(this, "", "人脸识别成功!");ui->weChatBtn->setEnabled(true);killTimer(check_id);}}}}}//关闭摄像头按钮对应的槽函数
void Widget::on_closeBtn_clicked()
{killTimer(camera_id);
}//录入人脸按钮对应的槽函数
void Widget::on_faceBtn_clicked()
{count = 0; // 将录入人脸的次数设置为0flag = 0; //表示只能做人脸录入,不能做人脸检测face_id = startTimer(50);}
main.c文件:
#include "widget.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}
ui布局: