此项目是基于人脸识别的考勤系统开发,包括如下模块:
1、人脸识别考勤系统GUI界面设计,包括:
(1)Qt环境(window环境/linux环境) ;
(2)Qt工程创建分析;
(3) Qt基本组件Qwidget QMainWindow,Qdialog,QLineEdit,Qlabel, QPushButton ;
(4)Qt界面布局,设计人脸识别考勤系统界面搭建;
(5)考勤机界面设计 (考勤默认界面, 数据录入界面,数据查询界面)。
2、考勤机界面逻辑与数据库实现,主要包括:
(1)Qt窗口切换
(2)Qt窗口间数据传递;
(3)人脸识别考勤机数据库及数据表的设计
3、人脸识别算法,主要包括:
(1)人脸识别算法分析及程序开发;
(2)opencv环境搭建;
(3)opencv采集人脸图像的程序开发;
(4)seetface人脸识别算法及程序开发。
4、人脸识别算法与Qt界面结合实现,主要包括:
(1)人脸检测及在Qt界面上的显示程序开发;
(2)人脸特征点提取及程序开发;
(3)人脸跟踪在Qt上显示;
(4)人脸信息采集存入数据库的编程;
(5)Qt线程Qthread应用,通过信号实现数据交换。
5、QT开发环境下的人脸识别考勤系统机整合调试,主要包括:
(1)在线程中处理人脸比对编程;
(2)比对数据写入考勤数据库的程序实现;
(3)在Qt界面显示比对结果并且提示考勤成功的程序开发;
(4)项目优化综合调试。
下述为QT的UI界面。
这里就是我们的代码层级结构了。
我们先看main.c
cpp
#include "faceproject.h"
#include <QApplication>
#include "seeta/FaceDetector.h" //人脸检测
#include "seeta/FaceRecognizer.h"
#include "seeta/FaceLandmarker.h"
#include "opencv.hpp"
#include <QDebug>
#include "QSqlDatabase"
#include <QSqlQuery>
#include <QSqlError>
using namespace seeta;
using namespace cv;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<Mat>("Mat");
qRegisterMetaType<Mat>("Mat&");
//打开数据库
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("./data/user.db");
if(!db.open())
{
qDebug()<<db.lastError().text();
}
//创建一个表格
QString createsql = "create table if not exists user (userid varchar(64) primary key,faceid int,username text, partment text, facename text)";
QSqlQuery query ;
query.exec(createsql);
//创建一个表格
createsql = "create table if not exists userrecord (id integer primary key autoincrement, userid varchar(64), cktime datatime)";
if(!query.exec(createsql))
{
qDebug()<<query.lastError().text();
}
FaceProject w;
w.show();
return a.exec();
}
功能解析
-
程序主框架
QApplication
是 Qt 桌面应用程序的核心类,用于管理应用的生命周期。FaceProject w; w.show();
表示创建了一个名为FaceProject
的主窗口对象,并将其显示。
-
SeetaFace 初始化
seeta::FaceDetector
,seeta::FaceRecognizer
, 和seeta::FaceLandmarker
分别是 SeetaFace SDK 提供的三大功能模块,用于人脸检测、识别、和关键点标注。虽然这些模块没有在代码中直接调用,但它们被#include
引入,表明可能在其他地方会使用。
-
OpenCV 的支持
cv::Mat
是 OpenCV 中的图像数据结构。qRegisterMetaType<Mat>("Mat")
和qRegisterMetaType<Mat>("Mat&")
将cv::Mat
类型注册到 Qt 的元对象系统中,方便在信号与槽机制中传递 OpenCV 的图像对象。
-
SQLite 数据库操作
- 打开数据库:
cpp
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("./data/user.db");
-
打开或创建一个 SQLite 数据库文件,路径为相对路径
./data/user.db
。 -
创建表格:
- 表
user
:存储用户的基本信息。
- 表
cpp
create table if not exists user (
userid varchar(64) primary key,
faceid int,
username text,
partment text,
facename text
);
userid
是用户唯一标识符。faceid
可能存储人脸特征 ID。- 其他字段存储用户姓名、部门、和人脸数据文件名等。
表 userrecord
:存储用户的考勤记录。
cpp
create table if not exists userrecord (
id integer primary key autoincrement,
userid varchar(64),
cktime datetime
);
id
是记录的自增主键。userid
关联用户表的userid
。cktime
是记录的时间戳。
错误处理
- 如果数据库打开失败,输出错误信息:
cpp
if(!db.open())
{
qDebug()<<db.lastError().text();
}
- 如果表格创建失败,输出 SQL 错误信息:
cpp
if(!query.exec(createsql))
{
qDebug()<<query.lastError().text();
}
主窗口启动
FaceProject
是一个自定义的类,继承自QWidget
或其子类。w.show()
表示显示主窗口,return a.exec();
开始事件循环。
下述就是SeetaFace 人脸识别库的应用的代码段了
cpp
seeta::ModelSetting FaceProject::FTSetting = seeta::ModelSetting("./model/fd_2_00.dat",seeta::ModelSetting::CPU,0);
FTSetting
是人脸检测模型的设置,使用 SeetaFace 库加载 fd_2_00.dat
模型,指定使用 CPU 模式。
cpp
FaceProject::FaceProject(QWidget *parent)
: QWidget(parent)
, ui(new Ui::FaceProject)
, mFTracker(FTSetting)
{
ui->setupUi(this);
capture.open(0);
if(!capture.isOpened()) {
qDebug()<<"open error";
}
Mat tempImage = imread("./image/background.jpeg"); // 显示的背景
tempImage.copyTo(backImage, mark2Image); // 截取除去头像外的背景
circ1Image = imread("./image/frontcircle.png");
circ2Image = imread("./image/backcircle.png");
// 初始化线程--识别(识别完后会收到query信号)
mthread = new QThread();
connect(this, &FaceProject::sendMat, &mRecognier, &QRecognizer::queryFace);
mRecognier.moveToThread(mthread);
mthread->start();
connect(&mRecognier, &QRecognizer::query, this, &FaceProject::queryResult);
startTimer(100); // 启动定时器,每100毫秒执行一次
camflag = false;
model = new QSqlTableModel();
model->setTable("user");
model->select();
ui->tableView->setModel(model);
}
- 人脸检测初始化 :创建
mFTracker
对象并初始化 SeetaFace 模型(fd_2_00.dat
)。 - 摄像头初始化 :使用 OpenCV 打开默认的摄像头设备(
capture.open(0)
)。 - 图片初始化:加载背景图和两个圆形头像图,用于显示用户头像。
- 线程和信号连接 :初始化识别线程
mthread
,并将sendMat
信号连接到mRecognier.queryFace
函数,完成异步的人脸识别操作。
cpp
QString selectsql = QString("select * from user where faceid=%1").arg(index);
QSqlQuery query;
query.exec(selectsql);
if(query.next()) {
QSqlRecord record = query.record();
QString numberstr = record.value("userid").toString();
QString namestr = record.value("username").toString();
QString partstr = record.value("partment").toString();
QString facepath = record.value("facename").toString();
ui->numberLb->setText(numberstr);
ui->nameLb->setText(namestr);
ui->partLb->setText(partstr);
ui->timeLb->setText(QTime::currentTime().toString("hh:mm:ss"));
Mat faceImage = imread(facepath.toUtf8().data());
showHeader(faceImage);
if (oldid != index && index != -1) {
oldid = index;
QString insertsql = QString("insert into userrecord(userid, cktime) values('%1','%2')")
.arg(numberstr).arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
if (!query.exec(insertsql)) {
qDebug() << query.lastError().text();
}
}
}
- 根据检测到的
index
查询数据库中的用户信息(user
表)并显示。 - 如果找到该用户的记录,会显示用户的
userid
、username
、partment
等信息。 - 将考勤记录插入
userrecord
表中,保存当前时间戳。
cpp
void FaceProject::showHeader(Mat &image) {
cv::resize(image, image, cv::Size(160, 160));
Mat circular;
image.copyTo(circular, circ2Image); // 使用圆形图像遮罩
addWeighted(circular, 1, circ1Image, 1, 3, image); // 将圆形头像图合并到原图
QImage image1(image.data, 160, 160, image.step, QImage::Format_RGB888);
ui->label_2->setPixmap(QPixmap::fromImage(image1));
}
将用户的头像调整为 160x160 大小,并加上圆形遮罩效果。
cpp
void FaceProject::showFaceVideo(Mat &image) {
cv::resize(image, image, cv::Size(480, 480));
cvtColor(image, image, COLOR_BGR2RGB); // 转换颜色空间
QImage vimage(image.data, 480, 480, image.step, QImage::Format_RGB888);
ui->label->setPixmap(QPixmap::fromImage(vimage));
}
将摄像头采集到的视频流调整为 480x480 并显示在界面上。