Python+Flask+dlib人脸识别考勤系统:从环境搭建到二次开发全解析
发布时间:2026/10/5 7:48:05 锦皓数字建站

简介这是一套面向高校计算机相关专业学生的高分毕业设计源码主题为基于Python、Flask与dlib的人脸识别企业考勤管理系统同时也可作为课程设计参考。项目已通过导师指导与答辩评审获得97分成绩并在Windows 10/11环境下完成严格调试下载后即可运行配套部署教程齐全。资源包共416个文件约103.71MB其中32个py文件承载Flask后端与dlib人脸识别核心逻辑26个html与118个js、61个css构成前端页面与交互样式另有79张jpg、51张png等图片资源用于界面展示与识别素材dat、xml等文件支撑模型与配置数据。目前已有170人学习关注。读者可获得完整可运行的项目源码、数据库与模型文件、前端静态资源以及使用文档便于快速理解人脸识别考勤的业务流程、接口设计与部署方式适合作为毕业设计、课程设计或Flask与计算机视觉入门实践的参考范例。1. 从一份 97 分毕设拆起Flask dlib 考勤系统到底能跑出什么如果你正在找一份能直接跑起来、答辩能讲清楚技术链路的毕业设计或者想拿一套现成的 Flask 项目改造成课程设计这套「基于 Python Flask dlib 的人脸识别企业考勤管理系统」值得认真拆一遍。它不是那种只放几张截图、代码跑不通的“论文配套压缩包”而是在 Windows 10/11 上完整调试过、带部署文档、答辩评审拿到 97 分的可运行项目。核心链路很清晰浏览器端调摄像头抓人脸后端用 dlib 做检测和特征提取Flask 负责路由与业务逻辑考勤记录落库后在前端页面展示。适合两类人一是需要快速搭出可演示系统的毕业生二是想理解人脸识别从算法到 Web 落地全流程的开发者。下面按“资源是什么 → 怎么装怎么跑 → 坑在哪 → 怎么改”的顺序拆开讲。2. 环境搭建与依赖安装把 dlib 和 Flask 同时伺候好2.1 为什么 dlib 是这套系统里最容易翻车的一环这套项目的技术栈里Flask 和前端资源Bootstrap、Summernote 等都是常规操作真正决定你能不能跑起来的是 dlib。dlib 的人脸检测和 68 点特征提取依赖 C 编译环境在 Windows 上直接pip install dlib大概率会卡在 CMake 或 Visual Studio Build Tools 缺失上。常见做法是先用 conda 建一个干净环境再通过 conda-forge 渠道装 dlib这样能绕过大部分编译问题。如果你坚持用 pip那就得先装好 Visual Studio 2019/2022 的 C 桌面开发组件和 CMake并且把 cmake 加入 PATH。我一般会推荐 Python 3.8 或 3.9因为 dlib 和 face_recognition 在这两个版本上的预编译包最全Python 3.11 以上容易遇到 wheel 缺失。2.2 从零建环境到依赖落地的完整命令# 创建 conda 环境指定 Python 3.8避免高版本 dlib 无预编译包 conda create -n attendance python3.8 -y conda activate attendance # 优先用 conda-forge 装 dlib它会自动处理 C 依赖 conda install -c conda-forge dlib -y # 安装 Flask 及项目所需的其他 Python 包 pip install flask flask-sqlalchemy flask-login opencv-python numpy pillow # 如果项目里用了 face_recognition再补装 pip install face_recognition这段命令的逻辑是conda 负责解决 dlib 的二进制依赖pip 负责装纯 Python 包。参数上-c conda-forge指定渠道-y跳过确认。装完后用python -c import dlib; print(dlib.__version__)验证能打印版本号就说明 dlib 通了。如果报ImportError: DLL load failed多半是 conda 环境没激活或者和系统里的其他 Python 冲突检查where python的输出顺序。2.3 数据库与项目配置的初始化项目一般用 SQLite 做默认数据库方便毕设演示。在项目根目录找到配置文件常见是config.py或app/config.py确认SQLALCHEMY_DATABASE_URI指向sqlite:///attendance.db。然后执行建表脚本# init_db.py 或类似入口手动建表 from app import db, create_app app create_app() with app.app_context(): db.create_all() print(数据表创建完成)这里的关键是db.create_all()必须在应用上下文里执行否则会报RuntimeError: Working outside of application context。如果项目用了 Flask-Migrate那就走flask db init、flask db migrate、flask db upgrade三步。建完表后检查数据库文件是否出现在instance/或项目根目录下有文件就说明落库成功。3. 人脸识别链路拆解从摄像头帧到考勤记录3.1 dlib 检测 特征提取的实际调用顺序这套系统的人脸识别不是黑匣子拆开看就是三步检测人脸框、提取 128 维特征向量、和库里的已知人脸比对。dlib 的get_frontal_face_detector()负责第一步shape_predictor_68_face_landmarks.dat负责定位五官face_recognition_model_v1负责把五官区域转成特征向量。项目里通常会封装一个face_utils.py或recognizer.py核心逻辑如下import dlib import face_recognition import numpy as np # 加载模型文件路径根据项目实际位置调整 detector dlib.get_frontal_face_detector() sp dlib.shape_predictor(models/shape_predictor_68_face_landmarks.dat) facerec dlib.face_recognition_model_v1(models/dlib_face_recognition_resnet_model_v1.dat) def get_face_encoding(image_path): # 读取图片并转为 RGBdlib 对 RGB 更友好 img face_recognition.load_image_file(image_path) # 检测人脸位置 face_locations face_recognition.face_locations(img, modelhog) if len(face_locations) 0: return None # 提取第一张人脸的特征向量 encodings face_recognition.face_encodings(img, face_locations) return encodings[0] if encodings else None参数说明modelhog是 CPU 版检测器速度快但小脸容易漏换成modelcnn精度更高但需要 GPU 或者耐心等。face_encodings返回的是 128 维 numpy 数组存库时可以用pickle或直接转成二进制。比对时用欧氏距离阈值一般设 0.6小于 0.6 判定为同一人大于 0.6 判定陌生人。这个阈值不是玄学是 dlib 官方推荐的经验值调低会拒真调高会认错。3.2 Flask 路由如何串起打卡业务前端页面通过navigator.mediaDevices.getUserMedia拿到摄像头流定时截帧传给后端/api/recognize接口。后端收到 base64 图片后解码调用上面的get_face_encoding再和数据库里User.face_encoding字段比对。匹配成功后写入Attendance表记录user_id、timestamp、status正常/迟到/早退。核心路由大概长这样from flask import Blueprint, request, jsonify import base64 import numpy as np import cv2 from app.models import User, Attendance, db from app.face_utils import get_face_encoding api_bp Blueprint(api, __name__) api_bp.route(/api/recognize, methods[POST]) def recognize(): data request.get_json() # 前端传过来的是 base64 编码的图片去掉前缀 img_data data[image].split(,)[1] img_bytes base64.b64decode(img_data) # 转成 numpy 数组供 OpenCV 处理 nparr np.frombuffer(img_bytes, np.uint8) img cv2.imdecode(nparr, cv2.IMREAD_COLOR) # 保存临时文件或直接传 numpy 给识别函数 encoding get_face_encoding_from_array(img) if encoding is None: return jsonify({code: 1, msg: 未检测到人脸}) # 遍历数据库里的用户特征做比对 users User.query.filter(User.face_encoding.isnot(None)).all() for user in users: known np.frombuffer(user.face_encoding, dtypenp.float64) dist np.linalg.norm(known - encoding) if dist 0.6: record Attendance(user_iduser.id, status正常) db.session.add(record) db.session.commit() return jsonify({code: 0, msg: f打卡成功{user.name}}) return jsonify({code: 2, msg: 未匹配到用户})这段代码里np.linalg.norm算的是欧氏距离和face_recognition.face_distance等价。User.face_encoding存的是二进制读出来要np.frombuffer还原。注意每次请求都查全表比对用户量大了会慢毕设场景够用生产环境得换向量数据库或者加缓存。3.3 前端页面与静态资源组织项目正文里列了一堆 CSS 文件bootstrap.min.css、summernote-bs3.css、style.css 等说明前端用了 Bootstrap 做响应式布局Summernote 做富文本编辑可能用于公告或日志模块。Flask 的静态文件默认放在static/目录模板放在templates/。启动后访问http://127.0.0.1:5000应该能看到登录页登录后进入考勤面板。如果页面样式错乱检查static/css/下的文件是否齐全以及模板里url_for(static, filename...)的路径拼写。常见问题是 Bootstrap 版本和 Summernote 版本不匹配导致弹窗样式异常换回项目自带的文件即可。4. 避坑与排查那些文档里不会写的血泪经验4.1 摄像头调用失败页面一直转圈现象点击“开始打卡”后浏览器没有弹出摄像头授权或者授权后画面黑屏。原因通常是浏览器安全策略限制getUserMedia只在 HTTPS 或 localhost 下生效。如果你用127.0.0.1:5000访问一般没问题但用局域网 IP 访问就会静默失败。解决本地开发就用 localhost或者用 Flask 的ssl_contextadhoc临时开 HTTPS。另外检查摄像头是否被其他程序占用Windows 的隐私设置里要允许桌面应用访问摄像头。4.2 dlib 模型文件路径写错报错找不到 .dat现象启动时报RuntimeError: Unable to open shape_predictor_68_face_landmarks.dat。原因模型文件没下载或者代码里的相对路径基于启动目录而不是项目根目录。解决确认models/目录下有两个 .dat 文件没有就去 dlib 官方渠道下载。路径建议用os.path.join(os.path.dirname(__file__), models, ...)拼绝对路径别用./models/...这种依赖工作目录的写法。4.3 人脸比对总是匹配到同一个人现象不同人打卡都显示同一个名字。原因特征向量存库时用了错误的 dtype比如存成 float32 读出来当 float64 用距离计算全乱。或者注册时只存了一张脸而那张脸光照条件特殊导致特征向量泛化差。解决统一用np.float64存取注册时至少采 3 张不同角度的照片取平均特征。阈值 0.6 不要随意调高超过 0.65 误识率会明显上升。4.4 Flask 热重载导致摄像头资源重复占用现象开发模式下改了代码Flask 自动重启但摄像头句柄没释放再打卡就报设备忙。原因Flask debug 模式会起两个进程一个监控一个运行摄像头资源被监控进程也初始化了一次。解决把摄像头初始化放在路由函数内部而不是模块顶层或者关掉 debug 模式的 reloaderapp.run(debugTrue, use_reloaderFalse)。4.5 数据库并发写入导致考勤记录丢失现象多人同时打卡时偶尔有人的记录没写进去。原因SQLite 默认锁机制在并发写时容易database is locked。解决毕设演示场景可以给db.session.commit()加 try-except 重试或者换 MySQL。如果坚持 SQLite在连接字符串里加?timeout10让写操作排队等待。5. 二次开发与验证把毕设改成能讲出亮点的作品5.1 换掉 HOG 检测器用 CNN 提升小脸检出率默认的 HOG 检测器在光线暗、人脸小的情况下漏检严重。如果你有 NVIDIA 显卡可以装dlib的 CUDA 版本然后把face_locations的model参数改成cnn。改完后同样一张图HOG 可能只检出 1 张脸CNN 能检出 3 张。代价是单帧处理时间从 50ms 涨到 300ms 左右打卡场景可以接受。验证方法准备一张多人合影分别用两种模型跑打印len(face_locations)对比。5.2 加一个活体检测的简易方案毕设答辩时老师常问“拿照片能不能打卡”。最简单的防御是眨眼检测用 dlib 的 68 点 landmark 算出眼睛纵横比EAR连续几帧 EAR 低于阈值再恢复判定为眨眼。代码片段def eye_aspect_ratio(eye_points): # eye_points 是 6 个点的坐标 A np.linalg.norm(eye_points[1] - eye_points[5]) B np.linalg.norm(eye_points[2] - eye_points[4]) C np.linalg.norm(eye_points[0] - eye_points[3]) return (A B) / (2.0 * C) # 连续帧里 EAR 先小于 0.2 再大于 0.25判定眨眼这个方案不能防视频回放但能挡住静态照片答辩够用。真要上生产得用红外双目或者 3D 结构光那是另一个量级的成本。5.3 考勤报表导出与数据验证项目一般自带考勤记录页面但导出 Excel 的功能不一定有。你可以用pandas加openpyxl补一个导出接口import pandas as pd from flask import send_file from io import BytesIO api_bp.route(/api/export) def export_attendance(): records Attendance.query.all() df pd.DataFrame([{ 姓名: r.user.name, 时间: r.timestamp.strftime(%Y-%m-%d %H:%M:%S), 状态: r.status } for r in records]) output BytesIO() df.to_excel(output, indexFalse) output.seek(0) return send_file(output, download_name考勤记录.xlsx, as_attachmentTrue)验证方法打卡几次后调这个接口打开 Excel 看时间戳和数据库里的是否一致。注意时区问题SQLite 存的是 UTC 还是本地时间取决于datetime.now()还是datetime.utcnow()导出前统一转换。5.4 从毕设到课程设计的降维用法如果你只是拿它当课程设计不需要完整考勤逻辑可以只保留人脸注册和识别两个页面把数据库换成 JSON 文件存储省去建表和迁移的麻烦。具体做法把User模型换成读写users.json特征向量用 base64 编码存字符串。这样部署时只需要 Python 和 dlib连数据库都不用装。我一般会建议先跑通完整版再按需裁剪别一上来就改架构否则出了问题都不知道是原项目的锅还是自己改的锅。从那以后我每次拿到这种带 dlib 的项目都强制先跑一遍python -c import dlib; print(dlib.__version__)再动其他文件确认底层依赖通了再往上叠业务。希望帮到你。本文还有配套的精品资源点击获取
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。