前言:
上篇我们已经用opencv实现了人脸识别https://blog.csdn.net/qq_42449351/article/details/99052241,现在我们就用人脸识别来做一个考勤管理系统。
该系统开发工具是 :win10,Qt Creator ,qt框架,opencv3.4.4, sqlite3
该系统分为用户考勤打卡系统和管理员管理系统。用户考勤打卡系统的功能有 1、实时显示当前时间;2、通过opencv实现人脸识别打卡;2、显示管理员发布的最新通知。管理员管理系统的功能有 1、对用户的信息进行录入; 2、查看当日考勤情况并进行统计 ;3、管理员发布和管理通知 ; 4、超级管理员添加和删除管理员
1、通过QT框架设计界面,包括用户考勤打卡界面、管理员的登录界面、用户信息管理界面、考勤统计等界面
2、通过sqlite3数据库将信息存储,如用户信息,打卡信息等。
3、通过opencv实现用户考勤打卡以及管理员登录,包括图像采集与预处理、模型训练以及将训练好的模型进行人脸识别
1、管理员信息表
2、用户信息表
//添加face模块的src文件
SOURCES += \
main.cpp \
armface.cpp \
src/bif.cpp \
src/eigen_faces.cpp \
src/face_alignment.cpp \
src/face_basic.cpp \
src/facemark.cpp \
src/facemarkAAM.cpp \
src/facemarkLBF.cpp \
src/facerec.cpp \
src/fisher_faces.cpp \
src/getlandmarks.cpp \
src/lbph_faces.cpp \
src/mace.cpp \
src/predict_collector.cpp \
src/regtree.cpp \
src/trainFacemark.cpp
HEADERS += \
armface.h \
face/bif.hpp \
face/face_alignment.hpp \
face/facemark.hpp \
face/facemark_train.hpp \
face/facemarkAAM.hpp \
face/facemarkLBF.hpp \
face/facerec.hpp \
face/mace.hpp \
face/predict_collector.hpp \
src/face_alignmentimpl.hpp \
src/face_utils.hpp \
src/precomp.hpp \
face.hpp
FORMS += \
armface.ui
//添加opencv路径
INCLUDEPATH+=D:\opencv64\include\
D:\opencv64\include\opencv\
D:\opencv64\include\opencv2
LIBS += D:\opencv64\x64\mingw\lib\libopencv_world344.dll.a
1、实时显示时间功能
该功能是通过定时器,每隔1秒获取当时时间,获得之后将时间显示在QLabel中,将星期几和月份变成相应的英文显示在label中,代码如下
//12个月的缩写
QString mouth[12] ={"Jan","Feb","Mar","Apr","May",
"June","July","Aug","Sept","Oct","Nov","Dec"};
connect(&timer,&QTimer::timeout,this,&ArmFace::run_time); //绑定定时器信号
timer.start(1000);
//将时间改变相应的格式显示在相应的label中
void ArmFace::show_time(int mm,QString dd, QString hhmm,QString dddd)
{
//显示时间
ui->label_4->setText(hhmm);
QString week;
if(dddd == "星期一") week = "Monday";
else if(dddd == "星期二") week = "Tuesday";
else if(dddd == "星期三") week = "Wednesday";
else if(dddd == "星期四") week = "Thursday";
else if(dddd == "星期五") week = "Friday";
else if(dddd == "星期六") week = "Saturday";
else if(dddd == "星期天") week = "Sunday";
QString data = week+" "+mouth[mm-1]+" "+dd;
ui->label_5->setText(data);
}
void ArmFace::run_time()
{
//获取当前时间
QString time = QDateTime::currentDateTime().toString("MM dd hh:mm dddd");
int mm = time.mid(0,2).toInt();
QString dd = time.mid(3,2);
QString hhmm = time.mid(6,5);
QString dddd = time.mid(12,4);
show_time(mm,dd,hhmm,dddd);
/*qDebug()<
2、通过opencv实现人脸识别
该功能是通过已训练好的文件,拿过来进行人脸识别,如果5次识别的结果都一样(这样做的效果是让识别更准确,减少误差),会拿这个识别的标签以及当天的日期,去数据库的考勤打卡表去查找是否存在该标签信息,如果没有该信息,会弹出 显示"姓名 : 打卡成功"的弹窗,并将该标签以及当前日期存储在考勤打卡表中;如果有该信息的话,会弹出 "姓名:您已打卡"的弹窗。
void ArmFace::on_openbt_clicked()
{
capture.open(0);
//训练好的文件名称,放置在可执行文件同目录下
cascade.load("haarcascade_frontalface_alt2.xml");
model = face::FisherFaceRecognizer::create();
//1.加载训练好的分类器
model->read("F:\\video\\AdminFace\\MyFaceFisherModel.xml");
ui->openbt->setStyleSheet("border-image:url(:/open.png)");
mtimer.start(20);
}
//将图片切成圆
QPixmap ArmFace::PixmapToRound(const QPixmap &src, int radius)
{
if (src.isNull()) {
return QPixmap();
}
QSize size(2*radius, 2*radius);
QBitmap mask(size);
QPainter painter(&mask);
painter.setRenderHint(QPainter::Antialiasing);
painter.setRenderHint(QPainter::SmoothPixmapTransform);
painter.fillRect(0, 0, size.width(), size.height(), Qt::white);
painter.setBrush(QColor(0, 0, 0));
painter.drawRoundedRect(0, 0, size.width(), size.height(), 150, 150);
QPixmap image = src.scaled(size);
image.setMask(mask);
return image;
}
//返回为识别的标签
int ArmFace::Predict(Mat src_image)
{
Mat face_test;
int predict = 0;
//截取的ROI人脸尺寸调整
if (src_image.rows >= 120)
{
//改变图像大小,使用双线性差值
::resize(src_image, face_test, Size(92, 112));
}
//判断是否正确检测ROI
if (!face_test.empty())
{
//测试图像应该是灰度图
predict = model->predict(face_test);
}
return predict;
}
识别5次,将识别的标签查找数据库(考勤打卡表)内是否存在
if(detection == Predict(pImage_roi[i]))
{
num++;
qDebug()<<"num"<openbt->setStyleSheet("border-image:url(:/close.png)");
return ;
}
return ;
}
//根据编号查询数据库(判断用户信息表中是否存在该用户)
QString sql = QString("select * from Stu where Sno='%1'").
arg(Predict(pImage_roi[i]));
QSqlQuery query(sql);
while(query.next())
{
num = 0;
flag = 0;
detection = 0;
qDebug()<openbt->setStyleSheet("border-image:url(:/close.png)");
//将打卡信息存在Attend(考勤打卡表)中
QString time = QDateTime::currentDateTime().toString("MM-dd hh:mm");
QString sql = QString("insert into Attend(Sno,time,State) values(%1,'%2',%3)").arg(Predict(pImage_roi[i])).arg(time).arg(1);
SqlQuery query;
if(!query.exec(sql))
{
qDebug()<<"add error";
}
else
{
qDebug()<<"添加成功";
}
}
num =0;
}
}
else {flag =0;qDebug()<<"不等";num = 0;}
detection = Predict(pImage_roi[i]);
将mat格式的数据显示在QLabel中
cvtColor(cap,cap,CV_BGR2RGB);
QImage image(cap.data, cap.cols, cap.rows, cap.step1() , QImage::Format_RGB888);
QPixmap mmp = QPixmap::fromImage(image);
mmp = mmp.scaled(ui->label_2->size());
mmp = PixmapToRound(mmp, 148);
ui->label_2->setPixmap(mmp);
3、显示管理员发布的最新通知
通过定时器每隔5分钟查询通知表的最后一条数据,即为管路员发布的最新通知,显示在QLabel中,
//查询通知消息
void ArmFace::run_message()
{
flag = 0;
QString sql_select = QString("select * from Release ");
QSqlQuery query_select(sql_select);
while(query_select.next())
{
flag++;
qDebug()<titlelabel->setText(title);
ui->contentlabel->setText(content);
ui->datalabel->setText(query.value(2).toString());
}
flag++;
}
}
至此我们用户考勤的三个功能已完全实现,接下来我们来看下运行效果
未打开摄像头界面
已经成功打卡后,再进行打卡,显示的界面
打卡成功,显示的界面
现在我们已经成功写好了用户打卡系统,下一篇我将为大家呈现管理员管理系统的设计,并将这两个工程项目的源代码分享给大家。跳转到下一篇请点击https://blog.csdn.net/qq_42449351/article/details/99753675