STM32全栈嵌入式人脸识别考勤系统:融合OpenCV、Qt和SQLite的解决方案

1. 项目概述

本项目旨在设计并实现一个基于STM32的全栈人脸识别考勤系统。该系统结合了嵌入式开发、计算机视觉和数据库技术,实现了自动人脸检测、识别和考勤记录功能。

主要特点:

  • 使用STM32F4系列微控制器作为主控制器
  • 采用OpenCV进行人脸检测和识别
  • Qt开发跨平台桌面应用程序,实现友好的用户界面
  • SQLite嵌入式数据库存储员工信息和考勤记录
  • 支持实时考勤、数据统计分析和报表生成

2. 系统设计

2.1 硬件设计

主要硬件模块及功能:

  • STM32F407VGT6微控制器:系统的核心,负责协调各个模块工作
  • OV7670摄像头模块:捕获实时图像,用于人脸检测和识别
  • 3.5寸TFT LCD显示屏:显示系统界面和识别结果
  • AS608指纹识别模块:作为辅助识别手段
  • RC522 RFID读卡器:用于员工卡识别,提供备用签到方式
  • ESP8266 WiFi模块:实现与服务器的无线通信,上传考勤数据

2.2 软件设计

3. 代码实现

3.1 人脸检测

以下是使用OpenCV实现人脸检测的代码示例:

#include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>using namespace cv;class FaceDetector {
private:CascadeClassifier face_cascade;public:FaceDetector(const std::string& cascade_file) {// 加载Haar级联分类器if (!face_cascade.load(cascade_file)) {throw std::runtime_error("Error loading face cascade file");}}std::vector<Rect> detectFaces(const Mat& frame) {Mat gray;std::vector<Rect> faces;// 转换为灰度图像cvtColor(frame, gray, COLOR_BGR2GRAY);// 执行人脸检测face_cascade.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));return faces;}void drawFaces(Mat& frame, const std::vector<Rect>& faces) {for (const auto& face : faces) {rectangle(frame, face, Scalar(255, 0, 0), 2);}}
};

代码说明:

  1. FaceDetector类封装了人脸检测功能。
  2. 构造函数加载Haar级联分类器文件。
  3. detectFaces方法接收一帧图像,返回检测到的人脸矩形区域。
  4. drawFaces方法在原图上绘制检测到的人脸矩形框。

 

3.2 人脸识别

下面是使用LBPH算法实现人脸识别的代码示例:

#include <opencv2/face.hpp>
#include <opencv2/opencv.hpp>using namespace cv;
using namespace cv::face;class FaceRecognizer {
private:Ptr<LBPHFaceRecognizer> model;public:FaceRecognizer() {model = LBPHFaceRecognizer::create();}void train(const std::vector<Mat>& faces, const std::vector<int>& labels) {model->train(faces, labels);}void predict(const Mat& face, int& label, double& confidence) {model->predict(face, label, confidence);}void saveModel(const std::string& filename) {model->save(filename);}void loadModel(const std::string& filename) {model->read(filename);}
};

代码说明:

  1. FaceRecognizer类封装了LBPH人脸识别器的功能。
  2. 构造函数创建LBPH人脸识别器实例。
  3. train方法用于训练模型。
  4. predict方法进行人脸识别,返回预测的标签和置信度。
  5. saveModelloadModel方法用于保存和加载训练好的模型。

3.3 数据库操作

使用SQLite进行数据库操作的代码示例:

#include <sqlite3.h>
#include <string>
#include <stdexcept>
#include <iostream>class Database {
private:sqlite3* db;static int callback(void* data, int argc, char** argv, char** azColName) {// 处理查询结果的回调函数for(int i = 0; i < argc; i++) {std::cout << azColName[i] << " = " << (argv[i] ? argv[i] : "NULL") << std::endl;}std::cout << std::endl;return 0;}public:Database(const std::string& dbName) {if (sqlite3_open(dbName.c_str(), &db) != SQLITE_OK) {throw std::runtime_error("Can't open database: " + std::string(sqlite3_errmsg(db)));}}~Database() {sqlite3_close(db);}void executeQuery(const std::string& sql) {char* errMsg = nullptr;int rc = sqlite3_exec(db, sql.c_str(), callback, 0, &errMsg);if (rc != SQLITE_OK) {std::string error = "SQL error: " + std::string(errMsg);sqlite3_free(errMsg);throw std::runtime_error(error);}}void insertEmployee(const std::string& name, int id) {std::string sql = "INSERT INTO employees (name, id) VALUES ('" + name + "', " + std::to_string(id) + ");";executeQuery(sql);}void recordAttendance(int employeeId, const std::string& timestamp) {std::string sql = "INSERT INTO attendance (employee_id, timestamp) VALUES (" + std::to_string(employeeId) + ", '" + timestamp + "');";executeQuery(sql);}
};

代码说明:

  1. Database类封装了SQLite数据库的基本操作。
  2. 构造函数打开数据库连接,析构函数关闭连接。
  3. executeQuery方法执行SQL查询,使用回调函数处理结果。
  4. insertEmployee方法插入新员工记录。
  5. recordAttendance方法记录考勤信息。

3.4 Qt界面实现

以下是使用Qt实现主界面的代码示例:

#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>
#include <QMessageBox>class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {setWindowTitle("人脸识别考勤系统");QWidget *centralWidget = new QWidget(this);QVBoxLayout *layout = new QVBoxLayout(centralWidget);QPushButton *btnAttendance = new QPushButton("考勤签到", this);QPushButton *btnManage = new QPushButton("员工管理", this);QPushButton *btnReport = new QPushButton("考勤报表", this);layout->addWidget(btnAttendance);layout->addWidget(btnManage);layout->addWidget(btnReport);setCentralWidget(centralWidget);connect(btnAttendance, &QPushButton::clicked, this, &MainWindow::onAttendanceClicked);connect(btnManage, &QPushButton::clicked, this, &MainWindow::onManageClicked);connect(btnReport, &QPushButton::clicked, this, &MainWindow::onReportClicked);}
private slots:void onAttendanceClicked() {// 打开考勤签到界面QMessageBox::information(this, "考勤签到", "正在打开摄像头进行人脸识别...");// 这里可以调用人脸识别和考勤记录的相关函数}void onManageClicked() {// 打开员工管理界面QMessageBox::information(this, "员工管理", "正在打开员工管理界面...");// 这里可以实现一个新的对话框或窗口来管理员工信息}void onReportClicked() {// 生成考勤报表QMessageBox::information(this, "考勤报表", "正在生成考勤报表...");// 这里可以实现报表生成和显示的功能}
};// 主函数
int main(int argc, char *argv[]) {QApplication app(argc, argv);MainWindow mainWindow;mainWindow.show();return app.exec();
}

代码说明:

  1. MainWindow类继承自QMainWindow,实现了主界面的布局和功能。
  2. 构造函数中创建了三个按钮:考勤签到、员工管理和考勤报表。
  3. 使用QVBoxLayout垂直布局来排列按钮。
  4. 通过connect函数将按钮的点击事件与相应的槽函数连接。
  5. 三个槽函数onAttendanceClickedonManageClickedonReportClicked分别处理不同按钮的点击事件。
  6. 主函数创建并显示主窗口,启动Qt事件循环。

3.5 STM32与Qt通信

以下是STM32与Qt程序通过串口通信的示例代码:

// STM32端代码(使用HAL库)
#include "stm32f4xx_hal.h"UART_HandleTypeDef huart2;void UART_Init(void) {huart2.Instance = USART2;huart2.Init.BaudRate = 115200;huart2.Init.WordLength = UART_WORDLENGTH_8B;huart2.Init.StopBits = UART_STOPBITS_1;huart2.Init.Parity = UART_PARITY_NONE;huart2.Init.Mode = UART_MODE_TX_RX;huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;HAL_UART_Init(&huart2);
}void SendData(uint8_t* data, uint16_t size) {HAL_UART_Transmit(&huart2, data, size, HAL_MAX_DELAY);
}// Qt端代码
#include <QSerialPort>
#include <QSerialPortInfo>class SerialCommunication : public QObject {Q_OBJECTpublic:SerialCommunication(QObject *parent = nullptr) : QObject(parent) {serial = new QSerialPort(this);connect(serial, &QSerialPort::readyRead, this, &SerialCommunication::handleReadyRead);}bool openPort(const QString &portName) {serial->setPortName(portName);serial->setBaudRate(QSerialPort::Baud115200);return serial->open(QIODevice::ReadWrite);}void closePort() {if (serial->isOpen()) {serial->close();}}void sendData(const QByteArray &data) {if (serial->isOpen()) {serial->write(data);}}private slots:void handleReadyRead() {QByteArray data = serial->readAll();emit dataReceived(data);}signals:void dataReceived(const QByteArray &data);private:QSerialPort *serial;
};// 在主窗口中使用SerialCommunication类
class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {serialComm = new SerialCommunication(this);connect(serialComm, &SerialCommunication::dataReceived, this, &MainWindow::onDataReceived);// 初始化串口if (serialComm->openPort("COM3")) {  // 根据实际情况修改串口名qDebug() << "Serial port opened successfully";} else {qDebug() << "Failed to open serial port";}}private slots:void onDataReceived(const QByteArray &data) {// 处理接收到的数据qDebug() << "Received data:" << data;// 这里可以添加对接收数据的处理逻辑}void sendCommandToSTM32(const QString &command) {serialComm->sendData(command.toUtf8());}private:SerialCommunication *serialComm;
};

代码说明:

  1. SerialCommunication类封装了Qt串口通信的功能。
  2. openPort方法用于打开指定的串口。
  3. closePort方法用于关闭串口。
  4. sendData方法用于发送数据到STM32。
  5. handleReadyRead槽函数处理接收到的数据,并通过信号dataReceived发送出去。
  6. MainWindow类中,我们创建了SerialCommunication实例,并连接了数据接收的信号和槽。
  7. onDataReceived槽函数用于处理从STM32接收到的数据。
  8. sendCommandToSTM32方法用于向STM32发送命令。

3.6 人脸识别与考勤逻辑集成

以下是将人脸识别与考勤逻辑集成到Qt应用程序中的示例代码:

#include <QCamera>
#include <QCameraImageCapture>
#include <QTimer>
#include <QDateTime>
#include <opencv2/opencv.hpp>class AttendanceSystem : public QObject {Q_OBJECTpublic:AttendanceSystem(QObject *parent = nullptr) : QObject(parent) {faceDetector = new FaceDetector("haarcascade_frontalface_default.xml");faceRecognizer = new FaceRecognizer();database = new Database("attendance.db");camera = new QCamera(this);imageCapture = new QCameraImageCapture(camera);connect(imageCapture, &QCameraImageCapture::imageCaptured, this, &AttendanceSystem::processCapturedImage);// 每5秒捕获一次图像QTimer *timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &AttendanceSystem::captureImage);timer->start(5000);}public slots:void startAttendance() {camera->start();}void stopAttendance() {camera->stop();}private slots:void captureImage() {imageCapture->capture();}void processCapturedImage(int id, const QImage &preview) {cv::Mat frame = QImageToMat(preview);std::vector<cv::Rect> faces = faceDetector->detectFaces(frame);for (const auto& face : faces) {cv::Mat faceROI = frame(face);int label;double confidence;faceRecognizer->predict(faceROI, label, confidence);if (confidence < 80.0) { // 假设置信度阈值为80recordAttendance(label);emit attendanceRecorded(label);}}}void recordAttendance(int employeeId) {QDateTime currentTime = QDateTime::currentDateTime();QString timestamp = currentTime.toString("yyyy-MM-dd hh:mm:ss");database->recordAttendance(employeeId, timestamp.toStdString());}private:FaceDetector *faceDetector;FaceRecognizer *faceRecognizer;Database *database;QCamera *camera;QCameraImageCapture *imageCapture;cv::Mat QImageToMat(const QImage &image) {cv::Mat mat;switch (image.format()) {case QImage::Format_RGB888:mat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR);break;case QImage::Format_ARGB32_Premultiplied:mat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());cv::cvtColor(mat, mat, cv::COLOR_RGBA2BGR);break;default:break;}return mat;}signals:void attendanceRecorded(int employeeId);
};

代码说明:

  1. AttendanceSystem 类集成了整个考勤系统的核心功能,包括摄像头控制、图像处理、人脸识别和考勤记录。

  2. 构造函数中:

    • 初始化 FaceDetectorFaceRecognizer 和 Database 对象。
    • 设置 QCamera 和 QCameraImageCapture 用于图像捕获。
    • 创建一个定时器,每5秒触发一次图像捕获。
  3. startAttendance() 和 stopAttendance() 方法用于启动和停止考勤过程。

  4. captureImage() 槽函数被定时器触发,用于捕获摄像头图像。

  5. processCapturedImage() 是核心处理函数:

    • 将 QImage 转换为 OpenCV 的 Mat 格式。
    • 使用 FaceDetector 检测人脸。
    • 对每个检测到的人脸进行识别。
    • 如果识别置信度高于阈值,则记录考勤。
  6. recordAttendance() 方法将考勤记录保存到数据库中,包括员工ID和时间戳。

  7. QImageToMat() 是一个辅助函数,用于将 Qt 的 QImage 转换为 OpenCV 的 Mat 格式。

  8. 类中定义了 attendanceRecorded 信号,当成功记录考勤时发出,可用于更新UI或通知其他组件。

  9. 整个系统通过定时捕获图像、检测人脸、识别身份、记录考勤的流程,实现了自动化的考勤功能。

  10. 该设计允许系统在后台持续运行,不需要人工干预即可完成考勤过程。

  11. 通过调整人脸识别的置信度阈值(此处设为80.0),可以平衡系统的准确性和灵敏度。

  12. 系统集成了数据库操作,确保考勤记录能够被永久保存和后续查询。

4. 项目总结

4.1 主要成果

  1. 成功实现了基于STM32和Qt的全栈人脸识别考勤系统。
  2. 集成了实时人脸检测和识别功能,提高了考勤效率。
  3. 开发了友好的用户界面,方便管理员操作和数据查询。
  4. 实现了考勤数据的自动化记录和统计分析功能。

4.2 技术亮点

  1. 采用OpenCV进行图像处理和人脸识别,提高了识别的准确性。
  2. 使用Qt框架开发跨平台桌面应用,提升了用户体验。
  3. 集成SQLite数据库,实现了高效的数据管理和查询。
  4. STM32与Qt的串口通信实现,使硬件控制更加灵活。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1483613.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

将达梦数据库的JDBC驱动包 DmJdbcDriver18.jar 安装到本地 Maven 仓库

项目打包报错&#xff1a;Failure to find com.dameng:DmJdbcDriver18:jar:8.1.3.12 in http://maven.aliyun.com/nexus/content/groups/public 解决方式如下&#xff1a; 从 https://eco.dameng.com/download/ 中下载 达梦JDBC 驱动包&#xff0c;如下 JDK 1.8 对应的 JDBC…

GPT LangChain experimental agent - allow dangerous code

题意&#xff1a;GPT LangChain 实验性代理 - 允许危险代码 问题背景&#xff1a; Im creating a chatbot in VS Code where it will receive csv file through a prompt on Streamlit interface. However from the moment that file is loaded, it is showing a message with…

大语言模型在病理AI领域中的应用2|文献速递·24-07-18

小罗碎碎念 本期文献主题&#xff1a;大语言模型在病理AI领域中的应用 本期推文是大模型4病理AI系列的第2期&#xff0c;每一篇文献都使用了ChatGpt&#xff0c;应用场景如下&#xff1a; 直接用ChatGpt生成回答比较多种主流大模型在指定任务中的性能表现比较大模型与专用模型…

【Linux】Linux环境设置环境变量操作步骤

Linux环境设置环境变量操作步骤 在一些开发过程中本地调试经常需要依赖环境变量的参数&#xff0c;但是怎么设置对小白来说有点困难&#xff0c;今天就介绍下具体的操作步骤&#xff0c;跟着实战去学习&#xff0c;更好的检验自己的技术水平&#xff0c;做技术还是那句话&…

【python】OpenCV—Scanner

文章目录 1、需求描述2、代码实现3、涉及到的库函数cv2.arcLengthcv2.approxPolyDPskimage.filters.threshold_localimutils.grab_contours 4、完整代码5、参考 1、需求描述 输入图片 扫描得到如下的结果 用OpenCV构建文档扫描仪只需三个简单步骤: 1.边缘检测 2.使用图像中…

HarmonyOS NEXT零基础入门到实战-第一部分

构建节页面思路&#xff1a; 1、排版 (分析布局) 2、内容&#xff08;基础组件&#xff09; 3、美化&#xff08;属性方法&#xff09; 设计资源-svg图标 界面中展示图标 ->可以使用svg图标&#xff08;任意放大缩小不失真&#xff0c;可以改颜色&#xff09; 使用方式&a…

Floyd 算法 求最短路

推荐阅读&#xff1a;最短路 - OI Wiki 练习题目&#xff1a;力扣 - 1334 简介&#xff1a; 初始化&#xff1a;我们先把题目给的&#xff0c;两点直接相连的边的加入初始存在连接中。更新&#xff1a;然后每次只加入一个点对已有合法连接进行“拓展”更多的连接。结果&#…

【python】OpenCV—Coordinates Sorted Clockwise

文章目录 1、需求介绍2、算法实现3、完整代码 1、需求介绍 调用 opencv 库&#xff0c;绘制轮廓的矩形边框&#xff0c;坐标顺序为右下→左下→左上→右上&#xff0c;我们实现一下转化为熟悉的 左上→右上→右下→左下 形式 按照这样的顺序组织边界框坐标是执行透视转换或匹…

数学基础【俗说矩阵】:矩阵相乘

矩阵乘法 矩阵乘法推导过程 一、两个线性方程复合代入 二、X1和X2合并同类项 三、复合后方程组结果 四、线性方程组矩阵表示 五、线性方程组矩阵映射表示 复合映射表示 六、矩阵乘法导出 矩阵乘法法则 1、规则一推导过程 左取行&#xff0c;右取列&#xff0c;对应相乘后…

第122天:内网安全-域信息收集应用网络凭据CS 插件AdfindBloodHound

目录 前置知识 背景和思路 判断是否在域内 案例一&#xff1a;架构信息类收集-网络&用户&域控等 案例二&#xff1a;自动化工具探针-插件&Adfind&BloodHound Adfind(域信息收集工具) ​BloodHound&#xff08;自动化域渗透工具&#xff09; 前置知识 本…

初阶数据结构的实现1 顺序表和链表

顺序表和链表 1.线性表1.1顺序表1.1.1静态顺序表&#xff08;不去实现&#xff09;1.1.2动态顺序表1.1.2.1 定义程序目标1.1.2.2 设计程序1.1.2.3编写代码1.1.2.3测试和调试代码 1.1.2 顺序表的问题与思考 1.2链表1.2.1链表的概念及结构1.2.1.1 定义程序目标1.2.1.2 设计程序1.…

专题四:设计模式总览

前面三篇我们通过从一些零散的例子&#xff0c;和简单应用来模糊的感受了下设计模式在编程中的智慧&#xff0c;从现在开始正式进入设计模式介绍&#xff0c;本篇将从设计模式的7大原则、设计模式的三大类型、与23种设计模式的进行总结&#xff0c;和描述具体意义。 设计模式体…

<数据集>木材缺陷检测数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;4000张 标注数量(xml文件个数)&#xff1a;4000 标注数量(txt文件个数)&#xff1a;4000 标注类别数&#xff1a;8 标注类别名称&#xff1a;[Quartzity,Live_Knot,Marrow,resin,Dead_Knot,knot_with_crack,Knot_m…

彻底解决idea的编解码问题

一、打开idea&#xff0c;找到Setting,点击File Encoding编解码设置&#xff0c;将以下标红的三个部分全部设置为UTF-8.同理如果你的项目使用的是GBK或者其他编码格式&#xff0c;那么也设置为统一。 二、点击Java Compiler设置补齐-encoding utf-8参数 三、如果你的项目使用到…

HiFi-GAN——基于 GAN 的声码器,能在单 GPU 上生成 22 KHz 音频

拟议的 HiFiGAN 可从中间表征生成原始波形 源码地址&#xff1a;https://github.com/NVIDIA/DeepLearningExamples 论文地址&#xff1a;https://arxiv.org/pdf/2010.05646.pdf 研究要点包括 **挑战&#xff1a;**基于 GAN 的语音波形生成方法在质量上不及自回归模型和基于流…

linux中list的基本用法

内核链表 1 list_head 结构 为了使用链表机制&#xff0c;驱动程序需要包含<linux/types.h>头文件&#xff0c;该文件定义了如下结构体实现双向链&#xff1a; struct list_head {struct list_head *next, *prev; };2 链表的初始化 2.1 链表宏定义和初始化 可使用以…

MongoDB教程(十二):MongoDB数据库索引

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; 文章目录 引言一、MongoD…

Vue封装文件上传组件(支持图片、PDF、Excel、word预览下载)

一、准备工作 安装预览依赖包&#xff1a;exceljs、mammoth、vue-pdf 二、封装组件 文件上传组件 fileUploadPro.vue。默认预览、下载是true,可通过isPreView、isDownLoad控制 <template><div style"display: flex"><el-uploadmultipleaction&qu…

SSM 整合(Spring + MyBatis;Spring + Spring MVC)

1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC) 文章目录 1. SSM 整合(Spring MyBatis&#xff1b;Spring Spring MVC)2. 引入相关依赖3. SSM 整合3.1 创建包结构 4. Spring 整合 MyBatis4.1 编写 jdbc.properties4.2 编写 DataSourceConfig 数据源配置4.3 编…

大数减法c++

这里写目录标题 key key 检查减数和被减数的大小&#xff0c;大的放前&#xff0c;小的放后确定结果是正数&#xff0c;还是负数&#xff0c;即符号位从低位开始减如果a[i]<b[i]&#xff0c;则向高位借1当10&#xff0c;a[i1]–;a[i]10 #include <iostream> #include…