从头开始开发基于虹软SDK的人脸识别考勤系统(python+RTSP开源)(二)

今天咱们继续昨天的话题,今天的重点是看思路和代码了。废话不多说,直接上干货。

先说一句,为了省事,直接一个文件完成所有功能,可能在代码可读性上差一些,比较眼花缭乱哈哈。整个文件含空行代码共1931行;咱们一点点说。

先说一下配置环境问题,我使用的是conda,配置dev为phthon 3.9

一、环境问题:

首先是python库有哪些,见代码

# -*- coding: utf-8 -*-
import logging
import sys
import os
import cv2
import sqlite3
import numpy as np
import pyttsx3
import shutil
import zipfile
from datetime import datetime
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer, QDate, QPoint, QMutex,QPropertyAnimation, QEasingCurve
from PyQt5.QtGui import (QImage, QPixmap, QFont, QIcon, QPainter, QPen,
                         QColor, QLinearGradient, QCursor, QBrush)
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QLabel, QPushButton,
                             QTableWidget, QTableWidgetItem, QFileDialog, QMessageBox,
                             QVBoxLayout, QHBoxLayout, QFormLayout, QInputDialog, QDialog,
                             QDialogButtonBox, QLineEdit, QComboBox, QDateEdit, QTabWidget,
                             QSystemTrayIcon, QMenu, QAction, QSpinBox, QCheckBox, QStyleFactory,QSizePolicy,QGraphicsOpacityEffect )
import ctypes
from ctypes import c_void_p, c_int, c_float, c_char_p, Structure, POINTER
from ctypes import cdll
import lunardate
import threading
import pandas as pd
import requests
from bs4 import BeautifulSoup

 requirements.txt 文件内容,不用考虑版本号,这些库在安装的时候也是问题一堆的出。

altgraph==0.17.4
beautifulsoup4==4.13.3
certifi==2025.1.31
charset-normalizer==3.4.1
chinese-calendar==1.8.0
click==8.1.8
colorama==0.4.6
comtypes==1.4.10
dlib==19.24.2
greenlet==3.1.1
holidays==0.67
idna==3.10
importlib_metadata==8.6.1
lunardate==0.2.2
ntplib==0.4.0
Nuitka==2.6.7
numpy==1.23.5
opencv-python==4.5.5.64
ordered-set==4.1.0
packaging==24.2
pandas==2.2.3
pefile==2023.2.7
pillow==11.1.0
pyinstaller==6.12.0
pyinstaller-hooks-contrib==2025.1
pypiwin32==223
PyQt5==5.15.11
PyQt5-Qt5==5.15.2
PyQt5_sip==12.17.0
python-dateutil==2.8.2
python-dotenv==0.21.1
pyttsx3==2.90
pytz==2025.1
pywin32==308
pywin32-ctypes==0.2.3
PyYAML==6.0
requests==2.32.3
sip==6.10.0
six==1.17.0
soupsieve==2.6
SQLAlchemy==1.4.46
tomli==2.2.1
typing_extensions==4.12.2
tzdata==2025.1
urllib3==2.3.0
zipp==3.21.0
zstandard==0.23.0

其他依赖的内容:

CMAKE必须;还有微软的开发包,忘记具体是啥了,反正我机器上又visual studio。你pip install -r的时候就知道会出一堆错误 ,基本就是dlib的问题。对照提示解决就是,实在不懂,直接复制错误扔给AI回答。

二、开发工具

简单说一下工具哈

代码中我大部分都加了注释,实在嫌麻烦的可以用visual studio code 安装codeX,选择代码加注释给你解释就好了,其实CODE这个插件特别多,很好用!以前我用的是sublime text,后来就完全被code替代了。

codeX让我卸载了?可能是嫌他介入的太多了,用TONGYI灵码也很好。

三、功能实现代码

# 配置日志记录
logging.basicConfig(filename='app.log', level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s')

关键点:虹软SDK的常量和结构定义

# 定义虹软SDK相关常量
ASF_FACE_DETECT = 0x00000001
ASF_FACERECOGNITION = 0x00000004
ASF_AGE = 0x00000008
ASF_GENDER = 0x00000010
ASF_FACE3DANGLE = 0x00000020
ASF_LIVENESS = 0x00000080
ASF_IR_LIVENESS = 0x00000400

ASF_DETECT_MODE_VIDEO = 0x00000000
ASF_DETECT_MODE_IMAGE = 0xFFFFFFFF
ASF_OP_0_ONLY = 0x1

ASF_PAF_RGB24_B8G8R8 = 0x201


# 虹软SDK结构定义
class ASF_VERSION(Structure):
    _fields_ = [
        ("Version", c_char_p),
        ("BuildDate", c_char_p),
        ("CopyRight", c_char_p)
    ]


class ASF_ActiveFileInfo(Structure):
    _fields_ = [
        ("startTime", c_char_p),
        ("endTime", c_char_p),
        ("activeKey", c_char_p),
        ("platform", c_char_p),
        ("sdkType", c_char_p),
        ("appId", c_char_p),
        ("sdkKey", c_char_p),
        ("sdkVersion", c_char_p),
        ("fileVersion", c_char_p)
    ]


class MRECT(Structure):
    _fields_ = [
        ("left", c_int),
        ("top", c_int),
        ("right", c_int),
        ("bottom", c_int)
    ]


class ASF_SingleFaceInfo(Structure):
    _fields_ = [
        ("faceRect", MRECT),
        ("faceOrient", c_int)
    ]


class ASF_MultiFaceInfo(Structure):
    _fields_ = [
        ("faceRect", POINTER(MRECT)),
        ("faceOrient", POINTER(c_int)),
        ("faceNum", c_int),
        ("faceID", POINTER(c_int))
    ]


class ASF_FaceFeature(Structure):
    _fields_ = [
        ("feature", c_void_p),
        ("featureSize", c_int)
    ]


class ASVLOFFSCREEN(Structure):
    _fields_ = [
        ("u32PixelArrayFormat", c_int),
        ("i32Width", c_int),
        ("i32Height", c_int),
        ("ppu8Plane", POINTER(POINTER(c_int))),
        ("pi32Pitch", POINTER(c_int))
    ]

系统配置,换上你们自己的SDK,目录你们自己随便建立,./Arcsdk/libarcsoft_face_engine.dll,这个你放在哪里就改到哪里。

# 系统配置
class AppConfig:
    def __init__(self):
        self.db_name = "attendance.db"
        self.backup_dir = "backups"
        self.face_img_dir = "static/face_images"
        self.camera_img_dir = "static/camera_images"
        self.recognition_threshold = 0.7
        self.check_interval = 2000

        os.makedirs(self.backup_dir, exist_ok=True)
        os.makedirs(self.face_img_dir, exist_ok=True)
        os.makedirs(self.camera_img_dir, exist_ok=True)

        self.face_algorithm = 'arcsoft'
        self.arcsoft_appid = b"换上你自己的APPID"
        self.arcsoft_sdkkey = b"换上你自己的SDKKEY"
        self.arcsoft_lib_path = os.path.abspath("./Arcsdk/libarcsoft_face_engine.dll")
        # print(f"虹软SDK库文件路径: {self.arcsoft_lib_path}")  # 打印库文件路径

数据库部分:

# 数据库服务
class DatabaseService:
    def __init__(self):
        # 初始化锁对象
        self.lock = threading.Lock()
        try:
            self.conn = sqlite3.connect(config.db_name)
            with self.conn:
                self._initialize_db()
        except sqlite3.Error as e:
            print(f"数据库连接失败: {e}")
            raise

    def _initialize_db(self):
        cursor = self.conn.cursor()
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS staff (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                department TEXT DEFAULT '未分配',
                photo_path TEXT NOT NULL,
                face_encoding BLOB NOT NULL,
                created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
                is_active BOOLEAN DEFAULT 1
            )''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS attendance (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                staff_id INTEGER NOT NULL,
                check_time DATETIME NOT NULL,
                date TEXT NOT NULL, 
                check_type TEXT CHECK(check_type IN ('morning', 'noon', 'night')),
                is_holiday BOOLEAN,
                camera_id INTEGER,
                FOREIGN KEY(staff_id) REFERENCES staff(id)
            )''')
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS camera_config (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                camera_type TEXT CHECK(camera_type IN ('usb', 'rtsp')),
                rtsp_url TEXT,
                is_enabled BOOLEAN DEFAULT 0,
                is_connected BOOLEAN DEFAULT 0
            )''')
        self.conn.commit()

员工管理

以添加员工最为重要,需要导入照片后提取人脸特征码存储。


    def add_staff(self, name, department, photo_path, encoding):
        try:
            cursor = self.conn.cursor()
            cursor.execute('''
                INSERT INTO staff (name, department, photo_path, face_encoding)
                VALUES (?,?,?,?)''',
                           (name, department, photo_path, encoding if isinstance(encoding, bytes) else encoding.tobytes()))
            self.conn.commit()
            staff_id = cursor.lastrowid
            logging.info(f"成功添加员工,ID: {staff_id}, 姓名: {name}")
            return cursor.lastrowid
        except sqlite3.Error as e:
            self.conn.rollback()
            logging.error(f"添加员工失败: {e}")
            print(f"添加员工失败: {e}")
            raise

    def get_staff(self, staff_id=None):
        cursor = self.conn.cursor()
        if staff_id:
            cursor.execute('SELECT * FROM staff WHERE id=? AND is_active=1', (staff_id,))
            return cursor.fetchone()
        cursor.execute('SELECT * FROM staff WHERE is_active=1')
        return cursor.fetchall()

    def delete_staff(self, staff_id):
        try:
            cursor = self.conn.cursor()
            cursor.execute('UPDATE staff SET is_active=0 WHERE id=?', (staff_id,))
            self.conn.commit()
        except sqlite3.Error as e:
            print(f"删除员工失败: {e}")
            raise

还写了个数据备份的功能,简单的很,压缩存储文件

    def create_backup(self, backup_path):
        try:
            with zipfile.ZipFile(backup_path, 'w') as zipf:
                zipf.write(config.db_name)
                for root, _, files in os.walk(config.face_img_dir):
                    for file in files:
                        zipf.write(os.path.join(root, file))
        except Exception as e:
            print(f"备份数据失败: {e}")
            raise

    def close(self):
        if self.conn:
            self.conn.close()

今天先这些吧,时间有点晚了,准备撤退回家了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

报表控件stimulsoft操作:使用 Angular 应用程序的报告查看器组件

Stimulsoft Ultimate (原Stimulsoft Reports.Ultimate)是用于创建报表和仪表板的通用工具集。该产品包括用于WinForms、ASP.NET、.NET Core、JavaScript、WPF、PHP、Java和其他环境的完整工具集。无需比较产品功能,Stimulsoft Ultimate包含了…

【网络编程】WSAAsyncSelect 模型

十、基于I/O模型的网络开发 接着上次的博客继续分享:select模型 10.8 异步选择模型WSAAsyncSelect 10.8.1 基本概念 WSAAsyncSelect模型是Windows socket的一个异步I/O 模型,利用这个模型,应用程序 可在一个套接字上接收以Windows 消息为基…

从0开始的操作系统手搓教程43——实现一个简单的shell

目录 添加 read 系统调用,获取键盘输入 :sys_read putchar和clear 上班:实现一个简单的shell 测试上电 我们下面来实现一个简单的shell 添加 read 系统调用,获取键盘输入 :sys_read /* Read count bytes from the file pointed to by fi…

鸿蒙应用开发—数据持久化之SQLite

文章目录 SQLite简介创建数据库添加数据查询数据更新数据删除数据升级数据库使用事务参考 SQLite简介 SQLite是一个轻量级关系数据库,占用资源很少,只有几百KB的大小,无需服务器支撑,是一个零配置、事务性的SQL数据库引擎。 相对…

应急响应--流量分析

(一)Cobalt Strike流量特征分析 1.HTTP特征 源码特征: 在流量中,通过http协议的url路径,在checksum8解密算法计算后,32位的后门得到的结果是92,64位的后门得到的结果是93,该特征符…

初始化E9环境,安装Sqlserver数据库

title: 初始化E9环境,安装Sqlserver数据库 date: 2025-03-10 19:27:19 tags: E9SqlServer初始化E9环境,安装Sqlserver数据库 安装E9本地环境安装Sql server 数据库1、检查SQL Server服务是否开启2、检查SQL Server网络网络配置是否开启创建一个ecology数据库点击初始化数据库…

自然语言处理:无监督朴素贝叶斯模型

介绍 大家好,博主又来和大家分享自然语言处理领域的知识了,今天给大家介绍的是无监督朴素贝叶斯模型。 在自然语言处理这个充满挑战又极具魅力的领域,如何从海量的文本数据中挖掘有价值的信息,一直是研究者们不断探索的课题。无…

API调试工具的无解困境:白名单、动态IP与平台设计问题

引言 你是否曾经在开发中遇到过这样的尴尬情形:你打开了平台的API调试工具,准备一番操作,结果却发现根本无法连接到平台?别急,问题出在调试工具本身。今天我们要吐槽的就是那些神奇的开放平台API调试工具,…

VSCode 2025最新前端开发必备插件推荐汇总(提效指南)

🌟前言: 如果你是一名前端开发工程师,合适的开发工具能大大提高工作效率。Visual Studio Code (VSCode) 凭借其轻量级、高扩展性的特点,已成为众多前端开发者在win系电脑的首选IDE。 名人说:博观而约取,厚积而薄发。—…

小程序事件系统 —— 33 事件传参 - data-*自定义数据

事件传参:在触发事件时,将一些数据作为参数传递给事件处理函数的过程,就是事件传参; 在微信小程序中,我们经常会在组件上添加一些自定义数据,然后在事件处理函数中获取这些自定义数据,从而完成…

初阶数据结构(C语言实现)——4.2队列

目录 2.队列2.1队列的概念及结构2.2队列的实现2.2.1 初始化队列2.2.2 销毁队列2.2.3 队尾入队列2.2.4 队头出队列2.2.5获取队列头部元素2.2.6 获取队列队尾元素2.2.7获取队列中有效元素个数2.2.8 检测队列是否为空,如果为空返回非零结果,如果非空返回0 3…

linux 命令 cat

cat 是 Linux 中用于查看、创建和合并文件的常用命令,全称 concatenate(连接)。其核心功能是将文件内容输出到终端或重定向到其他文件/命令中。以下是详细用法及场景示例: 基本语法 cat [选项] [文件1] [文件2] ... 选项…

TON基金会确认冠名赞助2025香港Web3嘉年华,并将于4月8日重磅呈现“TON生态日”

近日,由万向区块链实验室与HashKey Group联合推出的Web3年度盛典——2025香港Web3嘉年华正式宣布,TON基金会确认成为本届嘉年华的冠名赞助商,并将于4月8日在主会场特别举办“TON生态日”专题Side Event,集中展现TON生态的最新技术…

【Java代码审计 | 第七篇】文件上传漏洞成因及防范

未经许可,不得转载。 文章目录 文件上传漏洞漏洞成因未验证文件类型和扩展名未限制文件上传路径 防范验证文件类型和扩展名验证文件内容限制文件上传路径使用安全的文件上传库 标准代码 文件上传漏洞 文件上传漏洞是指攻击者通过上传恶意文件(如可执行脚…

【无人机路径规划】基于麻雀搜索算法(SSA)的无人机路径规划(Matlab)

效果一览 代码获取私信博主基于麻雀搜索算法(SSA)的无人机路径规划(Matlab) 一、算法背景与核心思想 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种受麻雀群体觅食行为启发的元启发式算法&#xff0…

狮子座大数据分析(python爬虫版)

十二星座爱情性格 - 星座屋 首先找到一个星座网站,作为基础内容,来获取信息 网页爬取与信息提取 我们首先利用爬虫技术(如 Python 中的 requests 与 BeautifulSoup 库)获取页面内容。该页面(xzw.com/astro/leo/&…

DeepSeek教我写词典爬虫获取单词的音标和拼写

Python在爬虫领域展现出了卓越的功能性,不仅能够高效地抓取目标数据,还能便捷地将数据存储至本地。在众多Python爬虫应用中,词典数据的爬取尤为常见。接下来,我们将以dict.cn为例,详细演示如何编写一个用于爬取词典数据…

AI智能导航站HTML5自适应源码帝国cms7.5模板

源码名称:AI导航站HTML5自适应源码帝国cms7.5模板 开发环境:帝国cms 7.5 安装环境:phpmysql var code "4d33ef8e-9e38-43b9-b37b-38f75944ecc9" 带软件采集,可以挂着自动采集发布,无需人工操作&#xff0…

【贪心算法】将数组和减半的最小操作数

1.题目解析 2208. 将数组和减半的最少操作次数 - 力扣(LeetCode) 2.讲解算法原理 使用当前数组中最大的数将它减半,,直到数组和减小到一半为止,从而快速达到目的 重点是找到最大数,可以采用大根堆快速达到…

Apache XTable:在数据湖仓一体中推进数据互作性

Apache XTable 通过以多种开放表格式提供对数据的访问,在增强互作性方面迈出了一大步。移动数据很困难,在过去,这意味着在为数据湖仓一体选择开放表格式时,您被锁定在该选择中。一个令人兴奋的项目当在数据堆栈的这一层引入互作性…