简介这份资源是面向高校学生与深度学习入门者的毕业设计级人脸识别签到系统采用Python实现适合作为课程设计、毕设选题或工程练手项目。项目以深度学习模型完成人脸检测与识别并配套用户注册、登录、签到记录管理等Web功能整体难度适中经过助教老师审定评审分达到95分以上源码本地编译可运行。压缩包共27个文件约101.47MB包含8个py核心脚本、7个html页面模板、4个dat数据文件以及sqlite数据库、ini配置、css样式、mako模板、md说明与ttc字体等覆盖模型调用、后端接口、前端页面与数据存储各环节。目前已有308人学习关注。读者可获得完整可运行的源码工程、数据库结构与操作说明便于快速理解人脸识别签到系统的模块划分与实现思路并在此基础上进行二次开发或论文撰写。1. 从一张签到表说起深度学习人脸识别签到系统到底解决什么问题传统签到方式无非是纸质签名、刷卡、指纹前两种容易代签指纹在手指脱皮或出汗时识别率骤降。我见过一个实验室的考勤场景三十多人的组会用纸质签到表结果每次都有三四个幽灵签名。换成深度学习人脸识别签到系统后代签问题基本消失因为摄像头抓的是活人脸不是一张可以传递的纸。这个标题里的核心是基于深度学习的人脸识别签到系统 Python 实现它要解决的是用摄像头采集人脸通过深度学习模型提取特征并比对识别成功后自动写入签到记录。适合谁计算机、电子信息类做毕业设计的学生以及想快速搭一个可演示、可扩展的考勤原型的开发者。它不需要你从零训练一个 ResNet主流做法是用现成的人脸检测加特征提取模型把工程链路串起来。下面我按选型—搭环境—写核心模块—避坑—进阶的顺序把这条链路讲透。2. 人脸识别签到系统的技术选型为什么不是从零训练 CNN2.1 检测、对齐、特征提取三段式别一上来就端到端人脸识别签到系统的工程链路常见做法是拆成三段人脸检测找到人脸框、人脸对齐把关键点摆正、特征提取与比对输出一个向量算距离。很多新手一上来就想训一个端到端 CNN输入图片直接输出人名这条路在毕业设计里几乎必翻车——你需要每个身份几百张图采集成本极高而且换一个人就得重训。更稳的方案是检测用 MTCNN 或 RetinaFace特征提取用 FaceNet 或 ArcFace 这类度量学习模型。它们输出的是 128 维或 512 维的嵌入向量同一个人的向量距离近不同人距离远。签到系统只需要维护一个姓名 → 特征向量的库新来一张脸算它和库里所有向量的余弦相似度超过阈值就判定为某人。这样加人只需注册几张照片不用重训模型。ArcFace 相比 FaceNet 的差别在于损失函数加了角度间隔类间区分度更好在公开测试集上准确率更高。但代价是模型稍大推理慢一点。如果签到场景只有几十人FaceNet 的 128 维向量足够如果上百人且要求高准确率ArcFace 的 512 维更合适。选型时先问自己人数规模多少、对误识率容忍度多高、机器有没有 GPU。2.2 Python 生态里能直接用的库和模型Python 做人脸识别绕不开几个库OpenCV 负责读摄像头和图像预处理face_recognition 封装了 dlib 的模型开箱即用但依赖编译环境insightface 封装了 ArcFace 系列精度高支持 ONNX 推理MTCNN 有独立的 pip 包检测稳定。我一般会这样组合检测用 MTCNN对侧脸和小脸更稳特征提取用 insightface 的 buffalo_l 模型包比对用 numpy 算余弦相似度。这套组合在 CPU 上单帧推理约 200 到 500 毫秒GPU 上能到 30 毫秒以内签到场景完全够用。提示face_recognition 在 Windows 上装 dlib 经常编译失败如果不想折腾编译优先选 insightface 的 ONNX 推理路线pip 装完就能跑。2.3 签到系统的数据层设计别把特征向量存进 Excel签到系统有两类数据人员注册信息姓名、工号、特征向量和签到记录姓名、时间戳、抓拍图路径。特征向量是 512 维浮点数组存 Excel 或 CSV 会又慢又容易精度丢失。常见做法是用 SQLite 存人员表和签到表特征向量序列化成二进制或 JSON 存进 BLOB 字段也可以用 numpy 的 .npy 文件存向量库SQLite 只存姓名和文件索引。签到记录表建议加唯一约束防止同一个人一秒内被重复写入多条。字段至少包含id、person_name、sign_time、snapshot_path。snapshot_path 存抓拍图方便事后核对这也是答辩时能演示的亮点。3. 用 Python 把签到系统跑起来环境、注册、识别、写库四步3.1 环境搭建与依赖安装的最小命令先确认 Python 版本建议 3.8 到 3.10太新的版本有些库轮子还没跟上。用虚拟环境隔离依赖避免污染全局。# 创建并激活虚拟环境Windows python -m venv venv venv\Scripts\activate # Linux / macOS python3 -m venv venv source venv/bin/activate # 安装核心依赖 pip install opencv-python insightface onnxruntime numpy pillow这里 opencv-python 负责摄像头采集和图像读写insightface 提供检测和特征提取onnxruntime 是推理后端numpy 做向量运算pillow 处理图像格式转换。如果机器有 NVIDIA 显卡把 onnxruntime 换成 onnxruntime-gpu推理速度能提升数倍。注意insightface 首次运行会自动下载模型包buffalo_l 约 300MB需要网络通畅。下载后模型缓存在用户目录的 .insightface 文件夹之后离线也能用。3.2 人脸注册把姓名和特征向量写进库注册就是采集某个人的几张照片提取特征向量取平均存进数据库。下面是一个最小注册脚本。import cv2 import numpy as np import sqlite3 import json from insightface.app import FaceAnalysis # 初始化分析器指定检测和识别模型 app FaceAnalysis(namebuffalo_l) app.prepare(ctx_id0, det_size(640, 640)) # ctx_id0 用GPU-1 用CPU def register(name, image_paths): conn sqlite3.connect(checkin.db) cur conn.cursor() cur.execute(CREATE TABLE IF NOT EXISTS persons (name TEXT PRIMARY KEY, embedding TEXT)) feats [] for p in image_paths: img cv2.imread(p) faces app.get(img) # 检测提取 if len(faces) ! 1: print(f{p} 检测到 {len(faces)} 张脸跳过) continue feats.append(faces[0].normed_embedding) # 已归一化的512维向量 if not feats: print(没有有效人脸注册失败) return avg_feat np.mean(feats, axis0) avg_feat avg_feat / np.linalg.norm(avg_feat) # 再归一化 cur.execute(INSERT OR REPLACE INTO persons VALUES (?, ?), (name, json.dumps(avg_feat.tolist()))) conn.commit() conn.close() print(f{name} 注册成功使用 {len(feats)} 张有效图) register(zhangsan, [z1.jpg, z2.jpg, z3.jpg])逻辑说明app.get() 返回的每个 face 对象带 normed_embedding 属性已经是 L2 归一化的向量直接算余弦相似度就是点积。多张图取平均能降低单张图姿态和光照带来的波动。参数 det_size 控制检测输入分辨率640×640 是精度和速度的平衡点人脸特别小可以调到 1024但速度会下降。3.3 实时识别与签到写库识别环节从摄像头读帧检测人脸和库里所有向量比对超过阈值就写签到记录。import time THRESHOLD 0.45 # 余弦相似度阈值需按实际数据调 def load_db(): conn sqlite3.connect(checkin.db) cur conn.cursor() cur.execute(SELECT name, embedding FROM persons) rows cur.fetchall() conn.close() names [r[0] for r in rows] embs np.array([json.loads(r[1]) for r in rows]) return names, embs def checkin_loop(): names, embs load_db() conn sqlite3.connect(checkin.db) cur conn.cursor() cur.execute(CREATE TABLE IF NOT EXISTS records (id INTEGER PRIMARY KEY AUTOINCREMENT, person_name TEXT, sign_time TEXT, snapshot_path TEXT)) cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret: break faces app.get(frame) for f in faces: emb f.normed_embedding sims embs emb # 矩阵点积一次算完所有相似度 idx int(np.argmax(sims)) if sims[idx] THRESHOLD: name names[idx] ts time.strftime(%Y-%m-%d %H:%M:%S) snap fsnaps/{name}_{int(time.time())}.jpg cv2.imwrite(snap, frame) cur.execute(INSERT INTO records (person_name, sign_time, snapshot_path) VALUES (?,?,?), (name, ts, snap)) conn.commit() cv2.putText(frame, f{name} checked, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow(checkin, frame) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows() conn.close()逻辑说明embs emb 是矩阵乘法把当前人脸向量和库里所有向量一次性算点积比循环快得多。THRESHOLD 是核心参数0.45 是 ArcFace 归一化向量的常用起点实际要拿自己的数据测太低会误识把别人认成你太高会拒识本人认不出。建议用几张已知身份的图跑一遍看本人相似度分布和他人相似度分布取两者之间的值。3.4 阈值怎么定用 ROC 思路找平衡点阈值不是拍脑袋定的。做法是准备一组测试图每张标注真实身份跑一遍识别统计本人被正确识别的相似度和被误认为他人的最高相似度。把两组数画成分布取一个能同时压低误识率和拒识率的点。阈值误识率倾向拒识率倾向适用场景0.35偏高低内部宽松考勤0.45中等中等常规签到0.55低偏高高安全场景如果发现本人相似度普遍在 0.5 以上而他人最高只有 0.3那 0.4 就很安全。如果本人相似度只有 0.4 出头说明注册照片质量差或姿态差异大应该先补注册图而不是硬降阈值。4. 人脸识别签到系统避坑五个我踩过的真实问题4.1 现象摄像头画面正常但一张脸都检测不到原因OpenCV 读到的帧是 BGR 格式而有些模型期望 RGB或者 det_size 设得太小人脸在画面里占比低。解决确认传入 app.get() 的是原始 BGR 帧insightface 内部会处理如果自己做了颜色转换反而出错把 det_size 从 320 提到 640 或 1024小脸检测率会明显上升。4.2 现象同一个人白天能识别晚上或背光时识别失败原因特征提取模型对光照敏感暗光下人脸纹理丢失嵌入向量偏移。解决在摄像头旁加补光灯是最直接的软件层面可以在检测前做直方图均衡化cv2.equalizeHist 对灰度图或者用 CLAHE 做自适应对比度增强。但要注意增强过度会引入噪声反而降低相似度建议先小范围试。4.3 现象签到记录里同一个人连续出现十几条原因摄像头每秒读多帧同一个人在多帧里都被识别每帧都写库。解决加去重逻辑记录每个人上次签到时间比如 30 秒内不重复写或者在数据库层对 (person_name, 时间窗口) 做约束。我一般用内存字典缓存最近签到时间简单有效。4.4 现象注册时提示检测到多张脸注册失败原因注册照片背景里有其他人脸或者海报、照片里的人脸被误检。解决注册照选纯色背景、单人正面如果无法避免可以在 app.get() 后按人脸框面积排序取最大的那张而不是要求恰好一张。但这样有风险最好还是控制输入质量。4.5 现象换台机器跑模型加载报错或速度极慢原因onnxruntime 的 GPU 版本和 CUDA 版本不匹配或者目标机器没有对应显卡。解决在代码里做后端探测优先尝试 GPU失败则回退 CPU。insightface 的 ctx_id 参数设为 -1 就是强制 CPU。另外模型缓存路径在不同用户下不一样部署时把 .insightface 目录一起打包避免现场重新下载。5. 让签到系统更像一个作品活体检测与批量注册的实用技巧答辩或演示时评委常问两个问题拿照片能不能骗过系统和加一百个人要多久这两个问题决定了你的系统是玩具还是作品。先说活体检测。纯特征比对确实能被照片骗过因为照片里的脸也能提取出相似向量。轻量做法是加一个眨眼检测用 face 对象的 landmark 关键点算眼睛纵横比EAR连续几帧 EAR 低于阈值再恢复判定为眨眼。insightface 的 face 对象带 kps 属性包含双眼、鼻、嘴角五点足够算 EAR。另一种是纹理分析用 LBP 算子看人脸区域的高频细节打印照片会有明显的纹理差异。这两种都不需要额外训练模型几十行代码能加上演示效果立竿见影。再说批量注册。手动一张张传图太慢我一般写一个脚本扫描文件夹文件名就是姓名每人一个子文件夹放 3 到 5 张图自动遍历注册。关键点是注册后打印每个人的有效图数量和平均向量模长模长异常比如接近 0说明提取失败要单独检查。批量注册完用几张没参与注册的图做验证算一下本人相似度确认库是有效的。最后一个习惯把阈值、模型名、检测尺寸这些参数写进一个 config.py 或 JSON 配置文件不要散落在代码里。演示现场如果要调阈值改一个数字重启即可不用翻代码。我吃过这个亏现场改参数改错地方折腾了十分钟。希望帮到你。本文还有配套的精品资源点击获取