基于QT的人脸识别考勤管理系统【一】

2023-11-13

前言:

        上篇我们已经用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、用户信息表

3、考勤打卡表

4、通知信息表

四、用户考勤打卡系统设计 (☆☆)

工程目录解析

更改配置文件

//添加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()<<mm;
    qDebug()<<hhmm;
    qDebug()<<dddd;
    qDebug()<<time;*/
}

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"<<num;
     if(num == 5 || flag ==1)
     {
         //判断是否打卡,已打则不进行打卡,在考勤打卡表中查询
         QString Time = time+"%";
         QString sql_select = QString("select * from Attend where Sno='%1'and Time like '%2'").arg(Predict(pImage_roi[i])).arg(Time);
         QSqlQuery query_select(sql_select);
         while(query_select.next())
         {
             //在用户信息表根据对应的标签(学号)拿出名字
             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;
              
                 QString message = query.value(2).toString()+",您已打卡";
                 QMessageBox::about(this,"提示",message);

                 mtimer.stop();
                 capture.release();
                 ui->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()<<query.value(0).toInt()<<query.value(1).toString()<<query.value(2).toString();
              
               QString message = query.value(2).toString()+": 打卡成功";
               QMessageBox::about(this,"提示",message);
                    
               mtimer.stop();
               capture.release();
               ui->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()<<flag;
    }
    int m = flag-1;
    flag = 0;
    QSqlQuery query(sql_select);
    while (query.next()) {

        if(flag ==m)
        {
            QString title = query.value(0).toString();
            QString content = query.value(1).toString();
            qDebug()<<title<<content;
            ui->titlelabel->setText(title);
            ui->contentlabel->setText(content);
            ui->datalabel->setText(query.value(2).toString());

        }
        flag++;
    }
}

至此我们用户考勤的三个功能已完全实现,接下来我们来看下运行效果

四、用户考勤打卡系统效果图

未打开摄像头界面

已经成功打卡后,再进行打卡,显示的界面

打卡成功,显示的界面

现在我们已经成功写好了用户打卡系统,下一篇我将为大家呈现管理员管理系统的设计,并将这两个工程项目的源代码分享给大家。跳转到下一篇请点击https://blog.csdn.net/qq_42449351/article/details/99753675

问题咨询及项目源码请加群:

QQ群

名称:IT项目交流群

群号:245022761

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于QT的人脸识别考勤管理系统【一】 的相关文章

  • OpenCV 仅围绕大轮廓绘制矩形?

    第一次发帖 希望我以正确的方式放置代码 我正在尝试检测和计算视频中的车辆 因此 如果您查看下面的代码 我会在阈值处理和膨胀后找到图像的轮廓 然后我使用 drawContours 和矩形在检测到的轮廓周围绘制一个框 我试图在 drawCont
  • 多视图几何

    我从相距一定距离的两台相同品牌的相机捕获了两张图像 捕获了相同的场景 我想计算两个相机之间的现实世界旋转和平移 为了实现这一点 我首先提取了两张图像的 SIFT 特征并进行匹配 我现在有基本矩阵也单应性矩阵 然而无法进一步进行 有很多混乱
  • Qt/c++ 随机字符串生成[重复]

    这个问题在这里已经有答案了 我正在创建一个应用程序 需要生成多个随机字符串 几乎就像一个由一定长度的 ASCII 字符组成的唯一 ID 这些字符混合有大写 小写 数字字符 有没有 Qt 库可以实现这一点 如果没有 在纯 C 中生成多个随机字
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • BASH 脚本编译多个 C++ 文件 - OpenCV

    请参见在C 和OpenCV中调用其他文件中的函数 https stackoverflow com questions 24442836 call functions in other files in c and opencv 对于最初的问
  • 指纹奇异点检测

    我正在尝试确定指纹的核心点和增量点 我正在使用庞加莱指数方法 但我无法成功检测到这一点 而且我不明白为什么 First I divide the image in 15x15 blocks then I calculate the x an
  • QT/QML Android App,点击通知栏时打开应用程序

    我为 Android 应用程序制作了一个 QT 当我单击平板电脑中上面看到的按钮通知栏时 但是 如果单击通知 我的应用程序将打开 聚焦 不知道 并显示黑色窗口 简单来说怎么做呢 我的代码是 package org ays operation
  • (如何)我可以抑制未找到包配置文件的警告吗?

    我正在尝试创建一个CMakeLists txt尝试查找的文件Qt5 如果失败 则尝试回退到Qt4安装 该脚本到目前为止有效 但如果出现以下情况我总会收到警告Qt5未安装 注意FindQt5 cmake是由提供Qt5并且仅当以下情况时才可用Q
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • Qt mouseReleaseEvent() 未触发?

    我有一个显示图片的库 我们称之为 PictureGLWidget 其中 class PictureGLWidget public QGLWidget 所以 PictureGLWidget 扩展了 QGLWidget 在PictureGlWi
  • Qt WinRT 应用程序无法访问文件权限被拒绝

    我需要使用 Qt 和 FFMPEG 开发 WinRT 应用程序 我根据指令构建了 WinRT 的 ffmpeghere https github com Microsoft FFmpegInterop我可以将库与我的项目链接起来 现在我需要
  • 如何在带有预编译头的项目中使用google protobuf

    我有一个包含多个项目的解决方案 我的项目 但不是全部 使用预编译头 我决定使用 protobuf 但遇到了一个问题 在 protoc exe 从 proto 生成 pb h 后 我尝试包含标头并收到错误 预编译标头未包含在 pb h 中 我
  • 从布局中按名称获取小部件

    如果我想从 python Qt 的布局中获取特定的小部件 我应该如何进行 到目前为止我所做的 for i in range self ui horizontalLayout 14 count here it does fail name s
  • 从图像坐标获取对象的世界坐标

    I have been following this http docs opencv org modules calib3d doc camera calibration and 3d reconstruction html docume
  • 如何使用 python、openCV 计算图像中的行数

    我想数纸张 所以我正在考虑使用线条检测 我尝试过一些方法 例如Canny HoughLines and FLD 但我只得到处理过的照片 我不知道如何计算 有一些小线段就是我们想要的线 我用过len lines or len contours
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • QToolButton:更改菜单位置

    使用菜单时QToolButton菜单显示在按钮的正下方 有没有办法在按钮的左侧 右侧显示菜单 我知道这个问题不久前已得到回答 但我想为此问题添加新答案 因为接受的答案不再有效 实际上 更改 QToolButton 上的菜单位置非常容易 您需
  • 与 Qt 项目的静态链接

    我有一个在 Visual Studio 2010 Professional 中构建的 Qt 项目 但是 当我运行它 在调试或发布模式下 时 它会要求一些 Qt dll 如果我提供 dll 并将它们放入 System32 中 它就可以工作 但
  • Qt 布局,在小部件大小更改后调整到最小大小

    基本上我有一个QGridLayout里面有一些小部件 最重要的是 2 个标签 我用它们将图像绘制到屏幕上 好吧 如果用户愿意 他可以更改传入图像的分辨率 从而强制标签调整大小 我们假设标签的初始大小是320x240 用户将 VideoMod
  • Qt:测量事件处理时间

    我想测量我的应用程序中的哪些事件在主线程中需要很长时间才能执行 阻塞 GUI 或者至少是否有任何事件花费的时间超过 比如说 10 毫秒 显然 我对需要很长时间的任务使用线程和并发 但有时很难在其他线程中放入的内容和可以保留在 GUI 中的内

随机推荐

  • KaTeX使用

    前言 在 KaTeX KaTeX KATE X官网 有两张支持表 这里搬运过来以便于大家能够正确使用指令 这张表应该涵盖了纯 KaTeX KaTeX KATE X所有的功能 当然
  • u-boot的norflash驱动分析,以及一些调试信息

    Flash 存储器接口还有两个标准 CFI和JEDEC CFI为公共Flash接口 Common Flash Interface 用来帮助程序从Flash芯片中获取操作方式信息 而不用在程序中硬编码Flash的ID JEDEC用来帮助程序读
  • 怎么用计算机打开开发者模式,win10如何打开开发者选项模式

    我们的win10系统中自带有开发者选项模式 该模式为Win10技术预览版开发此风格应用你需要开启 开发者模式 开启之后 在将应用提交给微软进行测试和认证前 你可以先在本地计算机上进行部署和测试 为开发者们提供了自由发挥的空间 那么win10
  • Oracle date日期类型使用

    Oracle中将日期转换为字符串 需要设置日期格式 to char sysdate fmt fmt YYYY MM DD HH24 MI SS 结果 2021 03 04 19 42 50 fmt YYYY MM DD HH12 MI SS
  • 多线程-UncaughtException

    在多线程开发中 我们会面对很多的异常问题 但是 主线程的异常我们知道很方便捕获并且处理 但是对于子线程而言呢 package Thread UncaughtException program 多线程和IO descripton 传统方法无法
  • Java打印程序设计全攻略 .

    前言 在我们的实际工作中 经常需要实现打印功能 但由于历史原因 Java提供的打印功能一直都比较弱 实际上最初的jdk根本不支持打印 直到jdk1 1才引入了很轻量的打印支持 所以 在以前用Java Applet JSP Servlet设计
  • div盒模型宽高计算

    一 计算div盒模型宽高 div盒模型宽度 width 左右padding 左右border 不包含左右margin div盒模型高度 height 上下padding 上下border 不包含上下margin
  • Linux新手入门教程

    版权声明 本文为博主原创文章 遵循 CC 4 0 BY SA 版权协议 转载请附上原文出处链接和本声明 本文链接 https blog csdn net li3839 article details 80658514 下面给你讲解新手第一次
  • 怎么看有没有用到ajax,使用AJAX请求JSON数据。我没有看到结果

    我正在学习Angular JS 为什么我看不到任何结果 使用AJAX请求JSON数据 我没有看到结果 这是我的例子 HTML post desc JS var app angular module MyApp app controller
  • discuz伪静态设置方法

    首先 进入后台 全局 SEO设置 URL静态化 如图 接着打开 查看当前的Rewrite规则 下载合适规则
  • mac上使用svn

    第一步 使用Homebrew安装subversion Homebrew不知道怎么安装的话 请自行百度 brew install subversion 第二步 使用如下的命令进行检查是否安装了这个软件 brew list 得到如下结果 使用如
  • vue常用组件库

    Vue是主流的前端框架一 Vue js UI组件 element 饿了么出品的Vue2的web UI工具套件 Vux 基于Vue和WeUI的组件库 mint ui Vue 2的移动UI元素 iview 基于 Vuejs 的开源 UI 组件库
  • 32黑马QT笔记之QPixmap和QImage的相互转换

    32黑马QT笔记之QPixmap和QImage的相互转换 1 QPixmap与QImage的互相转换 1 头文件 void paintEvent QPaintEvent 2 实现 cpp文件 void Widget paintEvent Q
  • 敏捷开发系列终极之旅 第六站(像橄榄球运动一样富有激情的SCRUM)

    由来 为什么是Scrum Scrum原本的意思是橄榄球运动的一个专业术语 指 在橄榄球比赛中 双方前锋站在一起紧密相连 当球在他们之间投掷时他们奋力争球 在敏捷开发系列中 把一种开发流程命名为Scrum 其实就意味着 这种敏捷开发的流程 就
  • 解决Android手机root仍然出现adbd connot run as root in production build

    对于手机已经root 但是使用 adb root命令仍然出新adbd connot run as root in production build 原因是手机固件里面设置了adb shell 禁止root 解决方法 下载文件 http do
  • Linux文件、磁盘管理的一些命令:

    Linux文件 磁盘管理的一些命令 Num01 gt ls ls 列出目录的内容 linux文件或目录名称英文最长可有255个字符 中文最长127个字符 表示当前目录 以 开头的文件为隐藏文件 需要以 a参数才能显示 表示上级目录或父目录
  • Training a deep autoencoder or a classifier on MNIST digits_之调试运行与理解

    运行这个程序的主要目的 深入理解deep autoencoder 的基本原理和基本架构 搞明白是如何搭建起来的 弄清它是如何训练学习的 又是如何提取目标的特征的 最终又是怎样分类的 代码主程序如下 mnistdeepauto m plain
  • PHP计算时间差

    时间计算 距离现在多长时间 function format date time t time time f array 31536000 gt 年 2592000 gt 个月 604800 gt 星期 86400 gt 天 3600 gt
  • Web应用下实现定时任务简便方法

    在WEB应用下实现定时任务的简便方法 在web方式下 如果我们要实现定期执行某些任务的话 除了用quartz等第三方开源工具外 我们可以使用Timer和TimeTask来完成指定的定时任务 第一步 创建一个任务管理类 实现ServletCo
  • 基于QT的人脸识别考勤管理系统【一】

    前言 上篇我们已经用opencv实现了人脸识别https blog csdn net qq 42449351 article details 99052241 现在我们就用人脸识别来做一个考勤管理系统 该系统开发工具是 win10 Qt C