QT 第六天 人脸识别系统

.pro

#-------------------------------------------------
#
# Project created by QtCreator 2023-09-05T11:12:48
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = project
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui


INCLUDEPATH += 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

.h

#ifndef WIDGET_H
#define WIDGET_H

#include 
#include 
#include 
#include 
#include
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include
#include

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 faces;
    int cameraID;        //摄像头的定时器
    void timerEvent(QTimerEvent *event);  //定时器事件处理函数


    /**************************录入人脸的相关组件*********************************/
    Ptr recognizer;    //人脸识别器
    vector study_face;       //要录入的人脸容器
    vector 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/haarcascade_frontalface_alt2.xml"))
    {
        QMessageBox::information(NULL,"失败","人脸识别模型装载失败");
        return ;
    }

    //配置人脸识别器
    QFile file("D:/opencv/mtl/myFace.xml");

    //判断文件是否存在,如果存在,则直接下载,如果不存在,则创建一个人脸识别器
    if(file.exists())
    {
        //人脸存在,直接下载即可
        recognizer = FaceRecognizer::load("D:/opencv/mtl/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_BGR2GRAY);

        //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;

        //提示正在

        //获取ui界面中矩形框中框起来的人脸区域
        Mat face = src(faces[0]);

        //将该图像进行重新设置大小
        cv::resize(face,face,Size(50,50));

        //灰度处理
        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;  //以便于下一次录入

            //更新人脸模型
            //参数一:要进行更新的人脸数组
            //参数二:要更新的人脸标签数组
            //返回值:无
            recognizer->update(study_face,study_lab);

            recognizer->save("D:/opencv/mtl/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/mtl/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(30);

    //将按钮设置成不可用状态
    ui->inputFaceBtn->setEnabled(false);

    flag = 1;
    count = 0;


}

QT 第六天 人脸识别系统_第1张图片

QT 第六天 人脸识别系统_第2张图片

一、在C++和C中static关键字的用法?
首先,在C++中static修饰静态成员,静态成员包括静态成员变量和静态成员函数。

静态成员变量:

1>在修饰静态成员变量时,在定义成员变量前加关键字static,权限一般为public,

2>只是在类内声明,必须在类外定义,类外定义时可以给定初始值,也可以不给,不给初始值默认为0,

3>静态成员变量,不占类对象的内存空间,独立于类对象存在

4>静态成员变量的访问形式,可以通过类对象进行访问,也可以通过类名进行访问:类名::变量

5>多个类对象,共享类中的静态成员变量的空间,一个对象对其进行更改,所有类对象该成员都更改,从功能上说,相当于是一个全局变量

6>相比于全局变量而言,静态成员变量更能体现类的封装性

静态成员函数:

1>在定义成员函数前,加关键字static,那么该函数就是静态成员函数

2>和静态成员变量一样,静态成员函数不依附于任意一个类对象,功能上类似于全局函数

3>对于静态成员函数的调用:可以通过类对象进行调用,也可以通过类名直接调用:类名::函数名(实参列表)

4>在静态成员函数中,只能使用静态成员函数,不能使用非静态成员变量

5>在静态成员函数中,没有this指针,但是,跟同名的非静态成员函数不构成重载关系,原因是作用域不同

而在C中的static

1>修饰未初始化的全局变量,默认结果为0

2>修饰局部变量,延长生命周期,生命周期不是作用域

3>修饰函数只能在当前文件中调用,不可跨文件调用

4>修饰其他文件的全局变量,不可以使用extern引用

5>修饰指针不可以指向auto类型的地址:因为计算机先为静态变量分配空间,后再分配auto类型变量,不可以使用指针指向不存在的变量地址

二、在C++和C中const关键字的用法?
在C++中:

1>常引用可以引用非 常变量,常成员函数保护成员变量不被修改

2> 可以使用变量来更改自己的值,但是不能通过引用更改目标的值

3> 常用于函数形参,修饰形参引用后,为了保护形参数据不被修改

4>修饰函数的返回值,如果是值返回,修饰不修饰无所谓,如果返回值是指针或者引用,要保证不被修改,要用const进行修饰,保护形参保护返回值不被修改

5>修饰成员变量,表明该变量是常成员变量,必须使用初始化列表对其进行初始化,对成员子对象也是必须在初始化列表中对其进行显性调用

在C中:

const 不是存储类型,修饰变量

作用:修饰的变量不发生改变

1>const修饰的全局变量,值不变,变量的空间在静态区的只读段

2>const修饰的局部变量,值不变,变量的空间在栈区

3>const和指针:

                      const int *p *在const的右边,修饰的值,值不变,地址可以改变

                      int const *p *在const的右边,修饰的值,值不变,地址可以改变

                      int * const p *在const的左边,修饰的地址,地址不变,值可以改变

                      const int * const p 第一个const修饰的值,第二个const修饰的地址地址和值都不可                          以改变

                       int const * const p 第一个const修饰的值,第二个const修饰的地址

                      地址和值都不可以改变
三、详细说一下QT中基于TCP的通信中服务器端操作?

1>创建一个QTCPServer的类对象,该类对象就是一个服务器

2>将该对象调用listen函数设置成监听状态,监听时,可以监听指定的ip地址,也可以监听所有主机地址,可以通过指定端口号,也可以让该服务器自动选择

3>当有客户端发来连接请求时,该服务器就会自动发射一个newConnection信号,我们可以将该信号连接到自定义的槽函数中处理相关逻辑

4>在槽函数中,可以调用nextPendingConnection函数可以获取最新连接的客户端套接字的地址,我们可以将该套接字存入到客户端容器中

5>此时服务器已经和客户端建立连接请求了,如果有客户端向服务器发来数据,那么对应的客户端套接字就会发射一个readyRead的信号

6>读取套接字中的数据使用read,readLine,readAll函数来完成

7>向套接字中写入数据,可以使用write函数完成

8>关闭服务器,使用close来完成
四、详细说一下QT中基于TCP的通信中客户端操作?
1>实例化一个QTCPSocket的类对象

2>调用该对象的成员函数connectToHost连接到服务器,连接服务器时,需要给定服务器的ip和端口号

3>如果连接服务器成功,那么该客户端就会自动发射一个connected的信号,我们可以在该信号连接到槽函数中处理相关逻辑

4>如果服务器有数据向客户端发来,那么该客户端就会自动发射一个readyRead信号,我们可以在该信号对应的槽函数中处理数据

5>可以使用read,readLine,readAll读取客户端套接字中的数据

6>可以使用write向服务器发送数据

7>使用成员函数disConnectFromHos断开与服务器的连接

8>如果成功断开与服务器的连接,那么该套接字就会自动发射一个disconnect的信号
 

你可能感兴趣的:(qt,开发语言)