.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断开与服务器的连接文章来源:https://www.toymoban.com/news/detail-708383.html
8>如果成功断开与服务器的连接,那么该套接字就会自动发射一个disconnect的信号
文章来源地址https://www.toymoban.com/news/detail-708383.html
到了这里,关于QT 第六天 人脸识别系统的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!