.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;
/**************************第一模塊:關(guān)于攝像頭的相關(guān)組件**************************/
VideoCapture v;
Mat src; //原圖像
Mat rgb; //存放rgb圖像,因?yàn)閝t能識(shí)別的圖像色彩空間為rgb
Mat gray; //灰度圖
Mat dst; //均衡化圖像
CascadeClassifier c; //級(jí)聯(lián)分類器
vector<Rect> faces;
int cameraID; //攝像頭的定時(shí)器
void timerEvent(QTimerEvent *event); //定時(shí)器事件處理函數(shù)
/**************************錄入人臉的相關(guān)組件*********************************/
Ptr<FaceRecognizer> recognizer; //人臉識(shí)別器
vector<Mat> study_face; //要錄入的人臉容器
vector<int> study_lab; //要錄入的人臉標(biāo)簽
int studyId; //人臉錄入的定時(shí)器
int flag; //表示是否正在錄入人臉
int count; //記錄學(xué)習(xí)的次數(shù)
/**************************第三模塊:人臉檢測相關(guān)組件*****************************/
int checkId; //人臉檢測的定時(shí)器
};
#endif // WIDGET_H
.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//將登錄按鈕設(shè)置成不可用狀態(tài)
ui->loginBtn->setEnabled(false);
//啟動(dòng)攝像頭
if(!v.open(0))
{
QMessageBox::information(this,"錯(cuò)誤","打開攝像頭失敗");
return;
}
//將級(jí)聯(lián)分配器加載進(jìn)來
if(!c.load("D:/opencv/haarcascade_frontalface_alt2.xml"))
{
QMessageBox::information(NULL,"失敗","人臉識(shí)別模型裝載失敗");
return ;
}
//配置人臉識(shí)別器
QFile file("D:/opencv/mtl/myFace.xml");
//判斷文件是否存在,如果存在,則直接下載,如果不存在,則創(chuàng)建一個(gè)人臉識(shí)別器
if(file.exists())
{
//人臉存在,直接下載即可
recognizer = FaceRecognizer::load<LBPHFaceRecognizer>("D:/opencv/mtl/myFace.xml");
}else
{
//人臉不存在,直接創(chuàng)建
recognizer = LBPHFaceRecognizer::create();
}
//啟動(dòng)人臉檢測的定時(shí)器
checkId = this->startTimer(3000);
//設(shè)置人臉識(shí)別的可信度
recognizer->setThreshold(100);
flag = 0; //表明開始時(shí)就處于檢測過程中
}
Widget::~Widget()
{
delete ui;
}
//打開攝像頭按鈕對(duì)應(yīng)的槽函數(shù)
void Widget::on_openCameraBtn_clicked()
{
//啟動(dòng)定時(shí)器
cameraID = this->startTimer(20);
ui->cameraLab->show();
}
//關(guān)閉攝像頭按鈕對(duì)應(yīng)的槽函數(shù)
void Widget::on_closeCameraBtn_clicked()
{
//關(guān)閉定時(shí)器
this->killTimer(cameraID);
ui->cameraLab->hide();
}
//定時(shí)器事件處理函數(shù)
void Widget::timerEvent(QTimerEvent *event)
{
//判斷是哪個(gè)定時(shí)器到位
if(event->timerId() == cameraID)
{
//1.從攝像頭中讀取一張圖像
v.read(src); //得到原圖
//2.將圖像反轉(zhuǎn)
flip(src,src,1);
//3.將src的bgr圖像轉(zhuǎn)換為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圖構(gòu)造出一個(gè)qt能識(shí)別的圖像
QImage img(rgb.data,rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
//功能:通過其他圖像構(gòu)造出一個(gè)QImage圖像
//參數(shù)一:其他圖像的數(shù)據(jù)
//參數(shù)二:圖像的寬度
//參數(shù)三:圖像的高度
//參數(shù)四:每一行的字節(jié)數(shù)
//參數(shù)五:圖像的格式,24位圖,每一種顏色使用8位表示
//10.將圖像展示到lab中
ui->cameraLab->setPixmap(QPixmap::fromImage(img));
}
//判斷是否是人臉錄入定時(shí)器到位
if(event->timerId() == studyId)
{
//判斷ui界面是否有矩形框
if(faces.empty())return;
//判斷人臉識(shí)別器是否存在
if(recognizer.empty())return;
//提示正在
//獲取ui界面中矩形框中框起來的人臉區(qū)域
Mat face = src(faces[0]);
//將該圖像進(jìn)行重新設(shè)置大小
cv::resize(face,face,Size(50,50));
//灰度處理
cvtColor(face,face,CV_BGR2GRAY);
//均衡化處理
equalizeHist(face,face);
//將人臉放入學(xué)習(xí)容器中
study_face.push_back(face);
study_lab.push_back(1);
count++; //表明完成一次人臉的存放
if(count == 50) //已經(jīng)收集50張人臉進(jìn)行學(xué)習(xí)
{
count = 0; //以便于下一次錄入
//更新人臉模型
//參數(shù)一:要進(jìn)行更新的人臉數(shù)組
//參數(shù)二:要更新的人臉標(biāo)簽數(shù)組
//返回值:無
recognizer->update(study_face,study_lab);
recognizer->save("D:/opencv/mtl/myFace.xml");
//殿后工作
study_face.clear(); //清空人臉數(shù)組
study_lab.clear(); //清空標(biāo)簽數(shù)組
flag= 0; //表明
ui->inputFaceBtn->setEnabled(true);
this->killTimer(studyId);
QMessageBox::information(this,"成功","人臉錄入成功");
}
}
//判斷是否是人臉檢測的定時(shí)器到位
if(event->timerId() == checkId)
{
qDebug() <<"正在檢測";
//判斷是否處于檢測
if(flag == 0)
{
QFile file("D:/opencv/mtl/myFace.xml");
if(file.exists()) //表明人臉模型存在的基礎(chǔ)上進(jìn)行識(shí)別
{
if(faces.empty() || recognizer->empty()) return; //ui界面無矩形框或者沒有人臉識(shí)別器
//到此表明可以進(jìn)行檢測了
Mat face = src(faces[0]);
//重新設(shè)置大小,保持跟保存人臉時(shí)一致
cv::resize(face,face,Size(100,100));
//灰度處理
cvtColor(face,face,CV_BGR2GRAY);
//均衡化處理
equalizeHist(face,face);
//定義記錄檢測后返回的結(jié)果的變量
int lab = -1; //返回的圖像的標(biāo)簽
double conf = 0.0;//返回圖像的可信度
//將該人臉進(jìn)行預(yù)測
recognizer->predict(face,lab,conf);
qDebug() << "lab = " <<lab << "conf = " <<conf;
//對(duì)人臉識(shí)別后的結(jié)果進(jìn)行判斷
if(lab != -1)
{
ui->loginBtn->setEnabled(true);
}
}
}
}
}
//錄入人臉按鈕對(duì)應(yīng)的槽函數(shù)
void Widget::on_inputFaceBtn_clicked()
{
//啟動(dòng)人臉錄入的定時(shí)器
qDebug() << "開始錄入人臉";
studyId = this->startTimer(30);
//將按鈕設(shè)置成不可用狀態(tài)
ui->inputFaceBtn->setEnabled(false);
flag = 1;
count = 0;
}
一、在C++和C中static關(guān)鍵字的用法?
首先,在C++中static修飾靜態(tài)成員,靜態(tài)成員包括靜態(tài)成員變量和靜態(tài)成員函數(shù)。
靜態(tài)成員變量:
1>在修飾靜態(tài)成員變量時(shí),在定義成員變量前加關(guān)鍵字static,權(quán)限一般為public,
2>只是在類內(nèi)聲明,必須在類外定義,類外定義時(shí)可以給定初始值,也可以不給,不給初始值默認(rèn)為0,
3>靜態(tài)成員變量,不占類對(duì)象的內(nèi)存空間,獨(dú)立于類對(duì)象存在
4>靜態(tài)成員變量的訪問形式,可以通過類對(duì)象進(jìn)行訪問,也可以通過類名進(jìn)行訪問:類名::變量
5>多個(gè)類對(duì)象,共享類中的靜態(tài)成員變量的空間,一個(gè)對(duì)象對(duì)其進(jìn)行更改,所有類對(duì)象該成員都更改,從功能上說,相當(dāng)于是一個(gè)全局變量
6>相比于全局變量而言,靜態(tài)成員變量更能體現(xiàn)類的封裝性
靜態(tài)成員函數(shù):
1>在定義成員函數(shù)前,加關(guān)鍵字static,那么該函數(shù)就是靜態(tài)成員函數(shù)
2>和靜態(tài)成員變量一樣,靜態(tài)成員函數(shù)不依附于任意一個(gè)類對(duì)象,功能上類似于全局函數(shù)
3>對(duì)于靜態(tài)成員函數(shù)的調(diào)用:可以通過類對(duì)象進(jìn)行調(diào)用,也可以通過類名直接調(diào)用:類名::函數(shù)名(實(shí)參列表)
4>在靜態(tài)成員函數(shù)中,只能使用靜態(tài)成員函數(shù),不能使用非靜態(tài)成員變量
5>在靜態(tài)成員函數(shù)中,沒有this指針,但是,跟同名的非靜態(tài)成員函數(shù)不構(gòu)成重載關(guān)系,原因是作用域不同
而在C中的static
1>修飾未初始化的全局變量,默認(rèn)結(jié)果為0
2>修飾局部變量,延長生命周期,生命周期不是作用域
3>修飾函數(shù)只能在當(dāng)前文件中調(diào)用,不可跨文件調(diào)用
4>修飾其他文件的全局變量,不可以使用extern引用
5>修飾指針不可以指向auto類型的地址:因?yàn)橛?jì)算機(jī)先為靜態(tài)變量分配空間,后再分配auto類型變量,不可以使用指針指向不存在的變量地址
二、在C++和C中const關(guān)鍵字的用法?
在C++中:
1>常引用可以引用非 常變量,常成員函數(shù)保護(hù)成員變量不被修改
2> 可以使用變量來更改自己的值,但是不能通過引用更改目標(biāo)的值
3> 常用于函數(shù)形參,修飾形參引用后,為了保護(hù)形參數(shù)據(jù)不被修改
4>修飾函數(shù)的返回值,如果是值返回,修飾不修飾無所謂,如果返回值是指針或者引用,要保證不被修改,要用const進(jìn)行修飾,保護(hù)形參保護(hù)返回值不被修改
5>修飾成員變量,表明該變量是常成員變量,必須使用初始化列表對(duì)其進(jìn)行初始化,對(duì)成員子對(duì)象也是必須在初始化列表中對(duì)其進(jìn)行顯性調(diào)用
在C中:
const 不是存儲(chǔ)類型,修飾變量
作用:修飾的變量不發(fā)生改變
1>const修飾的全局變量,值不變,變量的空間在靜態(tài)區(qū)的只讀段
2>const修飾的局部變量,值不變,變量的空間在棧區(qū)
3>const和指針:
? ? ? ? ? ? ? ? ? ? ? const int *p *在const的右邊,修飾的值,值不變,地址可以改變
? ? ? ? ? ? ? ? ? ? ? int const *p *在const的右邊,修飾的值,值不變,地址可以改變
? ? ? ? ? ? ? ? ? ? ? int * const p *在const的左邊,修飾的地址,地址不變,值可以改變
? ? ? ? ? ? ? ? ? ? ? const int * const p 第一個(gè)const修飾的值,第二個(gè)const修飾的地址地址和值都不可? ? ? ? ? ? ? ? ? ? ? ? ? 以改變
? ? ? ? ? ? ? ? ? ? ? ?int const * const p 第一個(gè)const修飾的值,第二個(gè)const修飾的地址
? ? ? ? ? ? ? ? ? ? ? 地址和值都不可以改變
三、詳細(xì)說一下QT中基于TCP的通信中服務(wù)器端操作?
1>創(chuàng)建一個(gè)QTCPServer的類對(duì)象,該類對(duì)象就是一個(gè)服務(wù)器
2>將該對(duì)象調(diào)用listen函數(shù)設(shè)置成監(jiān)聽狀態(tài),監(jiān)聽時(shí),可以監(jiān)聽指定的ip地址,也可以監(jiān)聽所有主機(jī)地址,可以通過指定端口號(hào),也可以讓該服務(wù)器自動(dòng)選擇
3>當(dāng)有客戶端發(fā)來連接請(qǐng)求時(shí),該服務(wù)器就會(huì)自動(dòng)發(fā)射一個(gè)newConnection信號(hào),我們可以將該信號(hào)連接到自定義的槽函數(shù)中處理相關(guān)邏輯
4>在槽函數(shù)中,可以調(diào)用nextPendingConnection函數(shù)可以獲取最新連接的客戶端套接字的地址,我們可以將該套接字存入到客戶端容器中
5>此時(shí)服務(wù)器已經(jīng)和客戶端建立連接請(qǐng)求了,如果有客戶端向服務(wù)器發(fā)來數(shù)據(jù),那么對(duì)應(yīng)的客戶端套接字就會(huì)發(fā)射一個(gè)readyRead的信號(hào)
6>讀取套接字中的數(shù)據(jù)使用read,readLine,readAll函數(shù)來完成
7>向套接字中寫入數(shù)據(jù),可以使用write函數(shù)完成
8>關(guān)閉服務(wù)器,使用close來完成
四、詳細(xì)說一下QT中基于TCP的通信中客戶端操作?
1>實(shí)例化一個(gè)QTCPSocket的類對(duì)象
2>調(diào)用該對(duì)象的成員函數(shù)connectToHost連接到服務(wù)器,連接服務(wù)器時(shí),需要給定服務(wù)器的ip和端口號(hào)
3>如果連接服務(wù)器成功,那么該客戶端就會(huì)自動(dòng)發(fā)射一個(gè)connected的信號(hào),我們可以在該信號(hào)連接到槽函數(shù)中處理相關(guān)邏輯
4>如果服務(wù)器有數(shù)據(jù)向客戶端發(fā)來,那么該客戶端就會(huì)自動(dòng)發(fā)射一個(gè)readyRead信號(hào),我們可以在該信號(hào)對(duì)應(yīng)的槽函數(shù)中處理數(shù)據(jù)
5>可以使用read,readLine,readAll讀取客戶端套接字中的數(shù)據(jù)
6>可以使用write向服務(wù)器發(fā)送數(shù)據(jù)
7>使用成員函數(shù)disConnectFromHos斷開與服務(wù)器的連接文章來源:http://www.zghlxwxcb.cn/news/detail-708383.html
8>如果成功斷開與服務(wù)器的連接,那么該套接字就會(huì)自動(dòng)發(fā)射一個(gè)disconnect的信號(hào)
?文章來源地址http://www.zghlxwxcb.cn/news/detail-708383.html
到了這里,關(guān)于QT 第六天 人臉識(shí)別系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!