基于深度学习的人脸识别考勤系统毕设源码全拆解

发布时间:2026/10/19 7:11:37
基于深度学习的人脸识别考勤系统毕设源码全拆解 简介这是一份面向计算机相关专业本科生的高分毕业设计项目——基于深度学习的人脸识别考勤系统使用 Python 实现人脸检测、特征提取、身份识别与考勤记录等核心流程可为课程设计、期末大作业或实际考勤场景提供完整参考。资源共 25 个文件包含 3 个 Python 主程序、15 张界面与背景图片、字体/图标文件以及接口配置、API 定义、打包好的软件和使用手册文档整体约 239MB目录划分明确便于按模块阅读。项目已获导师认可并取得 98 分评审成绩现有 166 人学习下载。压缩包内除可运行软件外还保留了 UI 设计素材、配置文件与操作说明手册能帮助读者快速掌握系统搭建思路、理解识别流程、替换界面元素并基于源码进行二次开发或论文撰写适合需要完整毕业设计源码与实战训练的学习者。1. 基于深度学习的人脸识别考勤系统一份能直接跑通的毕设源码到底该怎么拆每年毕设季都会有不少同学拿着这份「基于深度学习的人脸识别考勤系统」源代码找我问我同一句话这压缩包解压出来几十个文件到底该看哪个、该改哪个、答辩时老师问起来该怎么答。这套源码的本质是一个桌面端考勤应用用摄像头采集人脸本地完成检测、特征提取和比对最终把打卡记录写进数据库并配了一套完整的 GUI 界面。它不依赖云端服务模型加载和推理都在本机完成适合计算机专业的学生做毕业设计、课程设计也适合想系统性了解人脸识别落地流程的 Python 学习者。我拆过十几份同类项目这份的特点是工程结构完整、能端到端跑通但坑也集中在环境依赖和资源路径上下面对照着压缩包里的真实文件逐个拆解。2. 源码包结构拆解从 face-master 到 Ui_test_01.py每个文件是干什么的拿到压缩包后不要急着双击运行先把整个目录结构看明白。这套项目的工程组织方式和常见的 Flask 或 Django Web 项目不同它走的是「算法包 GUI 入口」的桌面应用路线解压后你会看到 face-master 目录、人脸识别-软件.zip、手册.docx、Ui_test_01.py、api 目录、static 目录以及一堆 .py 和 .png/.ico 资源文件。下面把关键文件逐个说明这是后续改动和答辩讲解的基础。2.1 face-master 目录与init.py算法库的封装边界该项目将核心人脸识别逻辑封装在 face-master 目录里并有__init__.py让整个目录可作为 Python 包被外部导入。很多初学者第一次看到这类目录名以为随便放其实这是整个项目的算法核心层通常包含人脸检测、特征提取、比对、注册和识别等子模块。__init__.py在 Python 3 里让目录变成可导入的包同时对外暴露关键类或函数。项目中个人更建议保持原封装边界不要在外部脚本里直接改包内属性。api 目录提供各功能接口__init__.py则是版本和模块的声明入口。这里最关键的一点是而项目里存取数据用的是数据库 ORM 还是原生 SQL可以直接看__init__.py里的导入语句——我拆过的版本中常见做法是用from face_main import FaceModel这样的语句导出核心类外部调用时只需from face_master import xxx即可。2.2 face.py 与 config识别主逻辑和参数配置的硬边界face.py 是本项目的主识别文件包含人脸检测、特征提取比对和注册的完整实现逻辑。config 则集中管理摄像头编号、阈值、数据库路径和模型路径等可调参数避免散落各处。个人认为这个设计值得肯定答辩时老师问「阈值参数在哪改」你能直接说出 config 文件就能体现出工程意识。face.py 中比较关键的是两类函数的区分一类是register_face负责录入新人脸并持久化特征另一类是recognize负责比对当前摄像头帧与库中特征返回匹配结果与置信度。项目中的参数表大致如下虽是常见配置但确实直接影响识别率参数项常见取值说明detection_modelmtcnn / hog / haarcascade检测器选型mtcnn 更准但更慢feature_modelfacenet / dlib-resnet特征提取网络直接决定向量维度match_threshold0.35 ~ 0.45欧氏距离阈值小于该值判定为同一人camera_index0 / 1摄像头编号笔记本一般用 0db_pathxxx.dbsqlite 数据库文件路径如果打开 face.py 看到的是 dlib 的get_frontal_face_detector加face_recognition库的face_encodings那就是最常见的技术路线64 维特征向量配合欧氏距离做判断。这种实现把「深度学习」落在特征提取阶段直接用预训练模型而检测器仍是传统 CV 方案辩时着重说明这一段即可。2.3 static 目录与 UI 资源改界面的真正入口static 目录下那一堆 png 图片、字体文件和 ico 图标不是装饰而是 GUI 的直接构成部分。llz_background.png是登录和主界面背景llz_userinfo_all.png是用户信息区域的底图llz_video_rect.png是视频画面的边框遮罩sign_status.png是打卡状态的图标资源empty_bg.png是默认头像。msyh.ttf是微软雅黑字体文件这套源码为了保证在不同 Windows 机器上界面不因字体缺失而乱码直接把字体打包进资源目录了——这是一个非常容易被忽略但很实用的细节如果部署到没有安装微软雅黑的精简系统界面文字会塌成方块字有了这个字体文件就能用 Qt 的字体加载接口规避这个问题。favicon.ico是窗口图标api目录里放的则是对外的业务接口封装把识别能力包装成可以被 UI 层调用的函数。Ui_test_01.py是主入口文件负责启动整个图形界面程序。整个 UI 层基于 PyQt 或 Tkinter 实现从Ui_test_01这个命名看它承担的是界面初始化、信号槽绑定和摄像头刷新循环的工作。static 目录中的图片资源虽然只是 png但你在 PyQt 中是通过setStyleSheet引用它们来定义整个界面的视觉风格。改界面首选这里不要动核心 face.py 里的逻辑。2.4 手册.docx 与软件压缩包先读手册再跑代码项目根目录里有两个看起来「不是代码」但很重要的文件手册.docx 和人脸识别-软件.zip。手册.docx 描述项目运行步骤、环境要求、接口说明和常见问题对应于教师在开题或中期检查时要求的文档。人脸识别-软件.zip 通常是打包好的可执行版本意味着经过 PyInstaller 或类似工具封装不依赖本地 Python 解释器也能运行但可能缺少完整模型文件或数据库结构不全。我的建议是先装好 Python 环境跑源码不要直接运行打包好的 exe。因为 exe 里的模型路径是写死的一旦你换机器可能找不到模型文件直接崩溃报错反而增加排障成本。源码跑通了再去看 exe确认未有的功能差异后才好用于演示。这个顺序能省掉至少一个小时的排查时间。3. 从零跑通系统环境搭建、数据库初始化和第一次人脸注册这段是整个实践操作的核心章节。许多同学拿到源码第一反应是直接python Ui_test_01.py结果 import 报错、缺库报错、模型路径报错连环出现。正确的推进顺序应该是创建虚拟环境 → 安装依赖 → 检查模型文件 → 初始化数据库 → 启动 UI → 注册人脸 → 测试打卡。3.1 Python 环境选型与依赖安装为什么必须用 3.7 或 3.8人脸识别类项目的依赖对 Python 版本相当敏感。dlib 库在 Python 3.9 以上的 Windows 环境下编译容易失败face_recognition 库依赖 dlibTensorFlow 的旧版本接口对 3.10 也不友好。这个项目里的常见依赖组合是 tensorflow、opencv-python、face_recognition、dlib、PyQt5 或 tkinter、numpy、Pillow。个人强烈建议使用 Python 3.7 或 3.8 的 64 位版本并新建虚拟环境不要把依赖装进全局环境——别问为什么问就是被坑过。虚拟环境的好处是即使依赖冲突删掉重建也就是几分钟的事不影响其他项目。# 创建并激活虚拟环境 conda create -n face_attendance python3.8 -y conda activate face_attendance # 安装核心依赖按顺序执行 pip install numpy1.19.5 pip install opencv-python4.5.5.64 pip install dlib19.22.0 pip install face_recognition1.3.0 pip install PyQt55.15.4这里有几个需要说明的点。numpy 指定 1.19.5 是因为新版 numpy 移除了一些旧接口后 dlib 和 face_recognition 会报np.floatattribute 错误这是近几年最经典的版本冲突没有之一。opencv-python 不需要装 opencv-contrib基础包已够用。dlib 的安装如果从源码编译会很折磨建议直接装预编译 wheelWindows 下推荐用pip install dlib19.22.0或下载对应版本轮子安装。PyQt5 用到的是 Qt 的界面框架5.15 系列对 Python 3.8 支持最稳定。依赖装完先做一次基础验证确认 import 无误后再进行下一步操作。验证命令如下# 验证核心依赖是否可导入 python -c import cv2, face_recognition, dlib, numpy; print(import ok) # 期望输出import ok如果 import 报错优先检查 Python 位数和依赖版本而不是急于去改项目代码。dlib 报错时在 Windows 上多与缺少 VC 运行库有关正常情况下装好依赖后即可在源码中运行。依赖这块只要版本对位十几分钟就能解决。3.2 模型文件与 config 参数检查跑通前必须对一遍路径第二个高频报错来源是模型路径。这个项目基于深度学习特征提取部分需要一个预训练模型文件常见的是 dlib 的dlib_face_recognition_resnet_model_v1.dat或 FaceNet 的 pb 模型。压缩包里没有模型文件的情况很常见——这不是压缩包的问题而是模型文件体积太大往往被单独下载或解压后补放。你需要先检查项目里有没有 .dat 或 .pb 后缀的文件如果没有去官方地址下载并放到 face-master 目录下然后在 config 中把模型路径指到该文件。config 文件里的路径在 Windows 上要格外注意反斜杠的转义。常见做法是使用绝对路径或os.path.join拼接避免硬编码。我见过最典型的翻车现场是同学把模型路径写成face-master/xxx.dat在 Windows 上运行时 Python 会把\f解析成换页符直接报路径不存在。解决方法如下# config.py 路径配置的正确写法 import os BASE_DIR os.path.dirname(os.path.abspath(__file__)) MODEL_PATH os.path.join(BASE_DIR, face-master, dlib_face_recognition_resnet_model_v1.dat) FACE_DB_PATH os.path.join(BASE_DIR, face_db.sqlite)这里必须说明两点。os.path.dirname(os.path.abspath(__file__))拿到的是当前文件所在的绝对目录无论你把项目移到哪个盘符都不会出现路径找不到的问题。相对路径在交互式命令行里是基于当前工作目录解析的一旦启动入口变了就会翻车。用这种动态拼接方式新手改不动、熟手看得懂答辩时也解释得清。3.3 数据库结构初始化搞清楚考勤记录存在哪这个项目的数据库多数使用 SQLite因为零配置、单文件、Python 内置支持。初始化时它会自动创建 student 信息表、face_feature 表、attendance_record 表等核心结构。如果没有现成的数据库文件启动第一次运行会自动建表但如果你是读到这里的读者我更建议在命令行先手工初始化一次确认表和字段符合预期再启动 UI。# initialize_db.py — 数据库初始化脚本 import sqlite3 conn sqlite3.connect(face_db.sqlite) cursor conn.cursor() # 用户信息表保存学号、姓名、照片路径 cursor.execute( CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, student_no TEXT UNIQUE NOT NULL, name TEXT NOT NULL, photo_path TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) # 人脸特征表保存特征向量以 BLOB 形式存储 cursor.execute( CREATE TABLE IF NOT EXISTS face_features ( user_id INTEGER NOT NULL, feature BLOB NOT NULL, model_name TEXT DEFAULT dlib_resnet, FOREIGN KEY(user_id) REFERENCES users(id) ) ) # 考勤记录表保存每次打卡信息 cursor.execute( CREATE TABLE IF NOT EXISTS attendance_records ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, check_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, status TEXT DEFAULT present, FOREIGN KEY(user_id) REFERENCES users(id) ) ) conn.commit() conn.close() print(database initialized)上面这段脚本里的三个表分别承担什么角色需要在这里讲透。users表管人员基础信息face_features表存的是特征向量的二进制序列也就是 face_recognition 输出的 128 维 float 数组序列化后的结果attendance_records表存打卡时间和出勤状态。三者通过user_id外键关联。像这种考勤系统的业务闭环在答辩时按「注册→提取特征→存储→比对→写记录」这条线讲老师能快速理解你的设计思路。值得一提的是有些版本会把特征直接存在 users 表的字段里而不是单独建表这种设计在数据量小的时候没问题但人脸特征文件动辄几百 KB单表查询会越来越慢。如果你拿到的版本是单表结构建议按上面的三表方案做一次轻量重构这会是答辩中的一个加分项。3.4 启动 GUI 并完成首次人脸注册数据库就绪后即可启动主程序python Ui_test_01.py界面弹出后先找到「注册」或「添加用户」的入口正常流程是输入学号和姓名 → 点击拍照或打开摄像头 → 程序自动从当前帧中检测人脸 → 提取特征向量并保存到数据库。注册过程中要保证光线均匀脸部正对摄像头不要戴墨镜或口罩否则检测框可能根本捕获不到人脸。常见的问题是注册时提示「未检测到人脸」。原因有两个一是摄像头编号不对程序中默认 camera_index0但在部分笔记本上外接摄像头可能是 1二是检测框画出来了但特征提取失败。摄像头的调整方法如下# camera_test.py — 快速测试摄像头是否可用 import cv2 for idx in range(3): cap cv2.VideoCapture(idx) if cap.isOpened(): print(fcamera {idx} available) ret, frame cap.read() if ret: print(fcamera {idx} read ok, frame shape: {frame.shape}) cap.release()这段脚本依次探测 0、1、2 号摄像头并尝试读取一帧正常情况下会打印出可用编号和画面尺寸。拿到可用编号后把它填到 config 的camera_index参数里重新启动程序问题即可解决。首次注册成功后再启动「识别」或「打卡」模式摄像头识别到该人脸就会在界面上显示姓名并在数据库写入一条打卡记录。4. 核心识别流程拆解人脸检测、特征提取和比对阈值是怎么串起来的上一章已经把系统跑起来了但如果你只停留在「能跑」的层面答辩时被问三个问题就会卡壳。这一章把 face.py 里的核心链路拆开摄像头帧进来后发生了什么每一步产出的数据结构是什么阈值调整对识别率的影响有多大以及考勤逻辑的边界条件在哪个环节处理。4.1 人脸检测从 OpenCV Haar 到深度学习检测器的选型逻辑检测阶段解决的是「脸在哪里」的问题。你打开 face.py大概率能看到两种实现传统的是cv2.CascadeClassifier加 Haar 特征进阶的是 MTCNN 或 dlib HOG。这个选型直接关系到运行速度与检测精度的平衡。Haar 检测器体积小、速度快但对侧脸、暗光、遮挡的鲁棒性较差适合课堂演示场景其原理是通过滑动窗口配合级联分类器快速排除非人脸区域但对旋转和表情变化的容忍度有限。MTCNN 是深度学习方案通过三阶段级联网络P-Net、R-Net、O-Net依次粗筛、精修、关键点对齐对姿态和光照更鲁棒但推理耗时显著增加。这个系统既然是对着摄像头做人脸识别考勤画面通常比较稳定用 dlib 的 HOG 或 Haar 就够了——HOG 在 CPU 上跑 30 fps 毫无压力而 MTCNN 在纯 CPU 环境下可能在 5 到 10 fps。如果你的电脑没有独立显卡建议直接沿用 HOG不要为了「深度学习」的名头强行上 MTCNN。人脸检测这一步产出的数据结构是一个矩形框列表每个框对应一张脸。常见的代码写法是这样的# detect_faces.py — 基于 dlib HOG 的人脸检测示意 import dlib detector dlib.get_frontal_face_detector() def detect_faces(frame, upsample_times1): # dlib 检测器输入是 RGB 图像OpenCV 默认读入 BGR此处需要转换 rgb_frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # upsample_times1 表示对图像做一次上采样能提升小脸检测率但耗时也翻倍 faces detector(rgb_frame, upsample_times) return faces这里的upsample_times很值得说一说。设为 0 时检测最快但半米以外的人脸可能漏检设为 1 时能多检出一些小目标速度仍然可接受设为 2 以上时检测率没有明显提升耗时反而成倍增加。通常 0.5 米到 2 米的考勤场景下upsample_times1是合理取值。输出结果faces是一个矩形对象集合每个face有left()、top()、right()、bottom()四个坐标值后续裁剪和特征提取都以这个坐标为基础。4.2 特征提取与比对128 维向量到底怎么比检测到人脸后下一步是截取人脸区域并交给特征提取器。dlib 的dlib_face_recognition_resnet_model_v1.dat模型会将 150x150 的 RGB 人脸图像映射为 128 维浮点向量。这个向量的坐标没有物理含义是从深度网络倒数第二层全连接层输出的嵌入表示它的特殊之处在于空间距离对应人脸的语义相似度——同一个人在不同光照、角度下的欧氏距离应当远小于不同人之间的距离。face_recognition 库对这个过程做了更友好的封装一步即可完成# encode_faces.py — 特征提取与比对示意 import face_recognition def encode_face(frame, face_location): # face_location 格式为 (top, right, bottom, left) face_encodings face_recognition.face_encodings(frame, [face_location]) if not face_encodings: return None # 返回 128 维特征向量 return face_encodings[0] def compare_features(known_feature, unknown_feature, threshold0.45): # face_distance 返回欧氏距离越小表示越相似 distance face_recognition.face_distance([known_feature], unknown_feature)[0] is_match distance threshold return is_match, distance核心在于第 16 行的face_distance计算与实际应用中阈值权衡的关系。distance 小于等于 threshold 判定为同一人大于则拒绝。阈值设得太小识别结果偏保守会出现「明明是同一个人却打不上卡」的误伤阈值设得太大又会出现「谁都能打上卡」的冒认风险。项目中的阈值默认设在 0.45 左右实际使用时要根据摄像头距离调整如果人脸离镜头较近、画面清晰阈值可以降到 0.38 提高准确率如果是在教室后排远距离识别0.48 到 0.50 更合适。4.3 考勤状态判定迟到、早退、缺勤的业务逻辑在哪一层很多人写这类系统只关注识别准不准忽略了一个问题识别通过之后考勤记录应该怎么写。打卡成功不代表状态就是「正常」还需要结合当前时间与设定的上下班时间做判断。这套逻辑通常不放在 face.py 里而是放在 api 目录的考勤接口中。一个典型的判定逻辑如下# attendance_check.py — 考勤状态判定逻辑示意 from datetime import datetime def judge_attendance(user_id, check_timeNone): if check_time is None: check_time datetime.now() # 定义上下班时间边界 morning_start check_time.replace(hour8, minute30, second0, microsecond0) morning_end check_time.replace(hour9, minute30, second0, microsecond0) afternoon_end check_time.replace(hour18, minute0, second0, microsecond0) if check_time morning_start: return present # 正常出勤 if check_time morning_end: return late # 迟到 if check_time afternoon_end: return early_leave # 早退或离岗 return present这段逻辑说明了一个关键设计考勤系统不仅仅是「识别出是谁」还要在业务层把识别结果与时间规则结合起来。项目中把这种判定逻辑独立出来的做法是合理的转换到毕业设计里你可以写「系统不仅实现了人脸比对还实现了迟到判断与统计功能」比单纯的人脸识别加分不少。另外需要注意打卡去重的问题。摄像头逐帧识别时如果同一人连续 30 帧都被识别成功数据库里就会插入 30 条打卡记录这属于业务逻辑缺陷。常见做法是引入「同一用户两次打卡间隔必须大于 N 分钟」的限制或用session_id来标识一次连续的识别会话# attendance_dedup.py — 打卡去重逻辑 def is_duplicate_record(user_id, last_records, interval_minutes5): last last_records.get(user_id) if last is None: return False delta (datetime.now() - last).total_seconds() / 60 return delta interval_minutes这个interval_minutes建议在 config 中配成 5 分钟或 10 分钟。人脸识别应用里「一次识别持续触发多次写入」是最容易被指出的问题把它处理掉系统才算完整。5. 实战避坑人脸识别考勤系统最常见的五个报错与处理本章聚焦我在拆解这个项目过程中遇到的、以及多位同学反馈的真实报错。每个问题都是「现象→原因→解决」的路径你可以直接对照排查。5.1 运行 Ui_test_01.py 直接报 ModuleNotFoundErrorNo module named face_master现象ModuleNotFoundError: No module named face_master程序启动即崩。原因face.py和 UI 文件中使用了from face_master import ...但你的当前工作目录不在项目根目录Python 的模块搜索路径里没有包含 face-master 所在的目录。很多同学在 PyCharm 中打开的是「项目内某个子目录」而不是「项目根目录」导致路径错位。解决确保以项目根目录为工作目录运行或在代码开头把根目录加入sys.path。# 在 Ui_test_01.py 文件头部加入以下两行如已有则跳过 import sys import os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))这样无论你从哪个目录启动解释器都会优先把当前文件所在目录即项目根目录加入模块搜索路径。PyCharm 中还有一种隐蔽情况是解释器版本不对需要确认当前 Project Interpreter 明确指向你创建的虚拟环境而不是全局环境。5.2 界面正常但摄像头画面黑屏或报错VIDEOIO ERROR: V4L2现象程序能打开窗口但摄像头画面区域是黑色的或直接抛出VIDEOIO ERROR: V4L2: cant open camera by index 0此问题在 Windows 上出现频率极高。原因摄像头被其他程序占用或者camera_index不对。线上答辩时你同时开着腾讯会议摄像头已经被会议软件独占这时再被 UI 程序调用必然失败如果你的笔记本有前置和后置摄像头编号不一定是 0。解决先关闭 Zoom、腾讯会议等占用摄像头的程序再运行考勤程序。如果仍然报错用上面的camera_test.py遍历 0 到 2 号摄像头把 config 中的camera_index改成正确编号。还有一种极端情况是 Windows 的隐私设置禁止应用访问摄像头需要在「设置→隐私→相机」里允许桌面应用使用摄像头。5.3 识别准确率低到无法正常打卡误识、拒识反复出现现象注册时用的照片是证件照识别时对着摄像头却打不上卡或者 A 同学的脸识别成了 B 同学。原因注册阶段提取的特征质量太差。证件照虽然是正脸但和摄像头实时帧的光照、角度差异过大更隐蔽的问题是注册时没有检测到人脸系统把背景当成了人脸区域提取特征存进数据库的是「背景特征」之后自然怎么比对都不匹配。解决删除数据库中该用户记录重新在真实使用环境下注册——即在宿舍正常光照下坐在摄像头前保持平时打卡的姿势重新录入。注意注册帧和识别帧的摄像头分辨率、画面比例要保持一致。部分版本在face.py的注册函数里有min_face_size或face_area_threshold参数如果注册时脸部像素宽小于 100 像素建议在识别前先看一眼显示比例靠近摄像头重新注册。5.4 GUI 界面中文全部显示为乱码或方块现象界面标题、按钮文字、用户名全都是问号或小方块完全无法辨认。原因PyQt5 的默认字体对中文字符不支持或者代码中没有加载中文字体。项目里自带msyh.ttf就是为了解决这个问题而放置的但很多同学没有调用它而是绕开了。解决在 UI 初始化代码中动态加载字体文件。# font_setup.py — 加载项目自带的中文字体 from PyQt5.QtGui import QFontDatabase def setup_font(font_path): font_id QFontDatabase.addApplicationFont(font_path) if font_id -1: print(font load failed) families QFontDatabase.applicationFontFamilies(font_id) if families: print(ffont family: {families[0]}) return families[0] return None # 调用方式需将字体完整路径传入例如 os.path.join(BASE_DIR, msyh.ttf)核心是addApplicationFont从文件加载字体到 Qt 的字体数据库再通过返回的 family 名称全局应用到 QApplication。不要直接在setFont里写「微软雅黑」四个字——在未安装该字体的系统上会直接回退到默认字体依然乱码。动态加载 TTF 文件是最稳妥的。5.5 打包成 exe 后模型路径找不到运行即闪退现象源码跑通了按网上的教程用 PyInstaller 打包成 exe双击之后窗口一闪就消失了控制台报错提示找不到.dat模型文件。原因PyInstaller 打包时不会自动把非代码文件模型、字体、图片复制进 dist 目录模型文件还在源目录里exe 却把当前工作目录切到了dist相对路径全部失效。解决打包时需要显式指定数据文件并在代码里用sys._MEIPASS兼容两种运行环境。# path_helper.py — 兼容源码运行与 PyInstaller 打包运行 import os import sys def resource_path(relative_path): # 打包后的 exe 运行时资源文件被解压到一个临时目录路径由 _MEIPASS 指定 if hasattr(sys, _MEIPASS): base_path sys._MEIPASS else: base_path os.path.abspath(.) return os.path.join(base_path, relative_path)使用resource_path(face-master/model.dat)来获取模型文件的绝对路径。同时打包命令要加上--add-data参数把模型和 static 目录下的所有资源一并打进去。我个人习惯是在.spec文件里显式定义datas列表而不是每次在命令行拼参数这样别人拿到 spec 文件也能复现你的打包配置。6. 给答辩加分的三个进阶改造阈值调节、报表导出和活体检测如果时间充裕不要停留在「能跑」的阶段。人脸识别考勤系统这个题目每年有大量人做想拿高分需要在「识别准确率」和「业务完整性」两个维度做出差异化。下面三个改造点按性价比排序都能在现有代码基础上较快完成。第一个实用改造是把比对阈值暴露到 GUI 界面上做成一个滑块控件。不要只停留在「config 文件里能改」的程度而是在 Qt 界面上增加一个 QSlider实时调整face_distance的判定阈值。demo 演示时你可以直接拖动滑块展示同一识别画面下距离 0.42 时识别成功、0.38 时识别失败这个交互效果比任何文字描述都更有说服力。实际做法是把从前端控件获得的阈值变量传入compare_features函数def on_threshold_changed(value): # 将滑块值0.30 ~ 0.60 之间直接写入全局配置 config.MATCH_THRESHOLD value / 100.0答辩时可以现场演示光线有变化时把阈值从 0.45 调到 0.50识别率恢复正常——这既展示了你对参数含义的理解又说明了系统有应对环境变化的调节能力。第二个高性价比改造是增加考勤记录的 Excel 导出功能。目前系统数据存在 sqlite查起来直观性不足展示起来也不够方便。可以加一个「导出日报表」按钮用 pandas 或 openpyxl 将attendance_records表按日期筛选后写成 Excel 文件。这个功能放在业务层面上讲就是「给教务或辅导员提供可归档的考勤数据」价值导向正向、实现难度低且和「考勤系统」这个题目高度契合。第三个改造属于进阶项活体检测。如果只是拿照片放在摄像头前就能打卡成功那这套系统在真实场景中是没有任何可用性的。常见做法是要求用户完成一个指定的动作眨眼、张嘴、摇头或计算两帧之间的人脸关键点位移。对毕设而言最简单的活体检测是要求用户先眨眼再识别代码实现是检测眼睛的纵横比# liveness_check.py — 通过眨眼检测的简易活体判断示意 def eye_aspect_ratio(eye_points): # 输入为眼睛关键点的坐标列表计算上下眼睑距离与左右眼距离的比值 vertical_a dist(eye_points[1], eye_points[5]) vertical_b dist(eye_points[2], eye_points[4]) horizontal dist(eye_points[0], eye_points[3]) return (vertical_a vertical_b) / (2.0 * horizontal) # EAR 值小于 0.2 判定为眨眼连续两帧眨眼则认定为活体这个逻辑虽然实现简单但在答辩现场演示时可信度高不少拿出照片放在摄像头前系统判定不是活体并拒绝打卡自己坐在镜头前正常眨眼后打卡成功。这个对比就是一个完整的「创新点」展示。说到最后结合我的个人经验想提醒一句毕设项目拿高分的关键永远不是「代码多难」而是「你有多了解自己的系统」。这套源码的价值在于它把检测、特征提取、比对、数据库、GUI 完整地串了起来给了你一个可以握在手里的完整产品。我在每次拿到新项目源码后都会花一个下午把face.py里每个关键函数的输入输出类型梳理成一张表格贴在注释里——从那以后不管是谁来问「这个参数能不能调、这个报错怎么解决」我都能在五分钟内指到具体文件的具体位置。这个习惯后来帮过很多同学希望也能帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询