• QT 第六天 人脸识别系统


    .pro

    1. #-------------------------------------------------
    2. #
    3. # Project created by QtCreator 2023-09-05T11:12:48
    4. #
    5. #-------------------------------------------------
    6. QT += core gui
    7. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    8. TARGET = project
    9. TEMPLATE = app
    10. SOURCES += main.cpp\
    11. widget.cpp
    12. HEADERS += widget.h
    13. FORMS += widget.ui
    14. INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include
    15. INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv
    16. INCLUDEPATH += D:/opencv/opencv3.4-qt-intall/install/include/opencv2
    17. LIBS += D:/opencv/opencv3.4-qt-intall/install/x86/mingw/lib/libopencv_*.a

    .h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include <QWidget>
    4. #include <opencv2/opencv.hpp>
    5. #include <iostream>
    6. #include <math.h>
    7. #include<opencv2/face.hpp>
    8. #include <vector>
    9. #include <map>
    10. #include <QMessageBox>
    11. #include <QDebug>
    12. #include <QFile>
    13. #include <QTextStream>
    14. #include <QDateTime>
    15. #include <QTimerEvent>
    16. #include<QtSerialPort/QtSerialPort>
    17. #include<QtSerialPort/QSerialPortInfo>
    18. using namespace cv;
    19. using namespace cv::face;
    20. using namespace std;
    21. namespace Ui {
    22. class Widget;
    23. }
    24. class Widget : public QWidget
    25. {
    26. Q_OBJECT
    27. public:
    28. explicit Widget(QWidget *parent = 0);
    29. ~Widget();
    30. private slots:
    31. void on_openCameraBtn_clicked();
    32. void on_closeCameraBtn_clicked();
    33. void on_inputFaceBtn_clicked();
    34. private:
    35. Ui::Widget *ui;
    36. /**************************第一模块:关于摄像头的相关组件**************************/
    37. VideoCapture v;
    38. Mat src; //原图像
    39. Mat rgb; //存放rgb图像,因为qt能识别的图像色彩空间为rgb
    40. Mat gray; //灰度图
    41. Mat dst; //均衡化图像
    42. CascadeClassifier c; //级联分类器
    43. vector<Rect> faces;
    44. int cameraID; //摄像头的定时器
    45. void timerEvent(QTimerEvent *event); //定时器事件处理函数
    46. /**************************录入人脸的相关组件*********************************/
    47. Ptr<FaceRecognizer> recognizer; //人脸识别器
    48. vector<Mat> study_face; //要录入的人脸容器
    49. vector<int> study_lab; //要录入的人脸标签
    50. int studyId; //人脸录入的定时器
    51. int flag; //表示是否正在录入人脸
    52. int count; //记录学习的次数
    53. /**************************第三模块:人脸检测相关组件*****************************/
    54. int checkId; //人脸检测的定时器
    55. };
    56. #endif // WIDGET_H

    .cpp

    1. #include "widget.h"
    2. #include "ui_widget.h"
    3. Widget::Widget(QWidget *parent) :
    4. QWidget(parent),
    5. ui(new Ui::Widget)
    6. {
    7. ui->setupUi(this);
    8. //将登录按钮设置成不可用状态
    9. ui->loginBtn->setEnabled(false);
    10. //启动摄像头
    11. if(!v.open(0))
    12. {
    13. QMessageBox::information(this,"错误","打开摄像头失败");
    14. return;
    15. }
    16. //将级联分配器加载进来
    17. if(!c.load("D:/opencv/haarcascade_frontalface_alt2.xml"))
    18. {
    19. QMessageBox::information(NULL,"失败","人脸识别模型装载失败");
    20. return ;
    21. }
    22. //配置人脸识别器
    23. QFile file("D:/opencv/mtl/myFace.xml");
    24. //判断文件是否存在,如果存在,则直接下载,如果不存在,则创建一个人脸识别器
    25. if(file.exists())
    26. {
    27. //人脸存在,直接下载即可
    28. recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/mtl/myFace.xml");
    29. }else
    30. {
    31. //人脸不存在,直接创建
    32. recognizer = LBPHFaceRecognizer::create();
    33. }
    34. //启动人脸检测的定时器
    35. checkId = this->startTimer(3000);
    36. //设置人脸识别的可信度
    37. recognizer->setThreshold(100);
    38. flag = 0; //表明开始时就处于检测过程中
    39. }
    40. Widget::~Widget()
    41. {
    42. delete ui;
    43. }
    44. //打开摄像头按钮对应的槽函数
    45. void Widget::on_openCameraBtn_clicked()
    46. {
    47. //启动定时器
    48. cameraID = this->startTimer(20);
    49. ui->cameraLab->show();
    50. }
    51. //关闭摄像头按钮对应的槽函数
    52. void Widget::on_closeCameraBtn_clicked()
    53. {
    54. //关闭定时器
    55. this->killTimer(cameraID);
    56. ui->cameraLab->hide();
    57. }
    58. //定时器事件处理函数
    59. void Widget::timerEvent(QTimerEvent *event)
    60. {
    61. //判断是哪个定时器到位
    62. if(event->timerId() == cameraID)
    63. {
    64. //1.从摄像头中读取一张图像
    65. v.read(src); //得到原图
    66. //2.将图像反转
    67. flip(src,src,1);
    68. //3.将src的bgr图像转换为rgb图像
    69. cvtColor(src,rgb,CV_BGR2RGB);
    70. //4.
    71. cv::resize(rgb,rgb,Size(300,300));
    72. //5.灰度处理
    73. cvtColor(rgb,gray,CV_BGR2GRAY);
    74. //6.均衡化处理
    75. equalizeHist(gray,dst);
    76. //7.
    77. c.detectMultiScale(dst,faces);
    78. //8.将矩形框绘制到rgb图像上
    79. for(int i=0;i<faces.size();i++)
    80. {
    81. rectangle(rgb,faces[i],Scalar(255,0,0),2);
    82. }
    83. //9.使用rgb图像将Mat图构造出一个qt能识别的图像
    84. QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
    85. //功能:通过其他图像构造出一个QImage图像
    86. //参数一:其他图像的数据
    87. //参数二:图像的宽度
    88. //参数三:图像的高度
    89. //参数四:每一行的字节数
    90. //参数五:图像的格式,24位图,每一种颜色使用8位表示
    91. //10.将图像展示到lab中
    92. ui->cameraLab->setPixmap(QPixmap::fromImage(img));
    93. }
    94. //判断是否是人脸录入定时器到位
    95. if(event->timerId() == studyId)
    96. {
    97. //判断ui界面是否有矩形框
    98. if(faces.empty())return;
    99. //判断人脸识别器是否存在
    100. if(recognizer.empty())return;
    101. //提示正在
    102. //获取ui界面中矩形框中框起来的人脸区域
    103. Mat face = src(faces[0]);
    104. //将该图像进行重新设置大小
    105. cv::resize(face,face,Size(50,50));
    106. //灰度处理
    107. cvtColor(face,face,CV_BGR2GRAY);
    108. //均衡化处理
    109. equalizeHist(face,face);
    110. //将人脸放入学习容器中
    111. study_face.push_back(face);
    112. study_lab.push_back(1);
    113. count++; //表明完成一次人脸的存放
    114. if(count == 50) //已经收集50张人脸进行学习
    115. {
    116. count = 0; //以便于下一次录入
    117. //更新人脸模型
    118. //参数一:要进行更新的人脸数组
    119. //参数二:要更新的人脸标签数组
    120. //返回值:无
    121. recognizer->update(study_face,study_lab);
    122. recognizer->save("D:/opencv/mtl/myFace.xml");
    123. //殿后工作
    124. study_face.clear(); //清空人脸数组
    125. study_lab.clear(); //清空标签数组
    126. flag= 0; //表明
    127. ui->inputFaceBtn->setEnabled(true);
    128. this->killTimer(studyId);
    129. QMessageBox::information(this,"成功","人脸录入成功");
    130. }
    131. }
    132. //判断是否是人脸检测的定时器到位
    133. if(event->timerId() == checkId)
    134. {
    135. qDebug() <<"正在检测";
    136. //判断是否处于检测
    137. if(flag == 0)
    138. {
    139. QFile file("D:/opencv/mtl/myFace.xml");
    140. if(file.exists()) //表明人脸模型存在的基础上进行识别
    141. {
    142. if(faces.empty() || recognizer->empty()) return; //ui界面无矩形框或者没有人脸识别器
    143. //到此表明可以进行检测了
    144. Mat face = src(faces[0]);
    145. //重新设置大小,保持跟保存人脸时一致
    146. cv::resize(face,face,Size(100,100));
    147. //灰度处理
    148. cvtColor(face,face,CV_BGR2GRAY);
    149. //均衡化处理
    150. equalizeHist(face,face);
    151. //定义记录检测后返回的结果的变量
    152. int lab = -1; //返回的图像的标签
    153. double conf = 0.0;//返回图像的可信度
    154. //将该人脸进行预测
    155. recognizer->predict(face,lab,conf);
    156. qDebug() << "lab = " <<lab << "conf = " <<conf;
    157. //对人脸识别后的结果进行判断
    158. if(lab != -1)
    159. {
    160. ui->loginBtn->setEnabled(true);
    161. }
    162. }
    163. }
    164. }
    165. }
    166. //录入人脸按钮对应的槽函数
    167. void Widget::on_inputFaceBtn_clicked()
    168. {
    169. //启动人脸录入的定时器
    170. qDebug() << "开始录入人脸";
    171. studyId = this->startTimer(30);
    172. //将按钮设置成不可用状态
    173. ui->inputFaceBtn->setEnabled(false);
    174. flag = 1;
    175. count = 0;
    176. }

    一、在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的信号
     

  • 相关阅读:
    安卓基础学习 Day19|安卓高级控件------下拉列表
    49-OpenCv深入分析轮廓
    JAVA高并发——线程池
    算法分析与设计 | 递归(数的计数)
    死锁的产生条件以及如何避免死锁
    安全信息化管理平台——数据分析与可视化
    大数据常见面试题:1
    [自动化]浅聊ansible的幂等
    Java数据结构——第八节-二叉树(全)(2.1万字)
    JavaScript-函数
  • 原文地址:https://blog.csdn.net/Meng_fighting/article/details/132698251