.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 <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/haarcascade_frontalface_alt2.xml"))
- {
- QMessageBox::information(NULL,"失败","人脸识别模型装载失败");
- return ;
- }
-
- //配置人脸识别器
- QFile file("D:/opencv/mtl/myFace.xml");
-
- //判断文件是否存在,如果存在,则直接下载,如果不存在,则创建一个人脸识别器
- if(file.exists())
- {
- //人脸存在,直接下载即可
- recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("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;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图像
- //参数一:其他图像的数据
- //参数二:图像的宽度
- //参数三:图像的高度
- //参数四:每一行的字节数
- //参数五:图像的格式,24位图,每一种颜色使用8位表示
-
- //10.将图像展示到lab中
- ui->cameraLab->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 = " <<lab << "conf = " <<conf;
-
- //对人脸识别后的结果进行判断
- if(lab != -1)
- {
- ui->loginBtn->setEnabled(true);
- }
-
- }
- }
- }
- }
-
-
- //录入人脸按钮对应的槽函数
- void Widget::on_inputFaceBtn_clicked()
- {
- //启动人脸录入的定时器
- qDebug() << "开始录入人脸";
-
- studyId = this->startTimer(30);
-
- //将按钮设置成不可用状态
- ui->inputFaceBtn->setEnabled(false);
-
- flag = 1;
- count = 0;
-
-
- }


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