首页 / 资讯中心 / 文章详情

Python目标检测人脸识别:Django企业考勤系统实战解析

Python目标检测人脸识别:Django企业考勤系统实战解析 ★ FEATURED ARTICLE
简介面向计算机毕业设计的企业考勤系统项目源码基于Django框架结合目标检测和人脸识别技术实现员工自动注册、人脸打卡、实时考勤监控、迟到早退等异常事件处理以及考勤数据报告生成等功能。后端采用Python 3.7编程语言数据库使用MySQL 5.7及以上版本可在PyCharm集成开发环境中配合Navicat数据库工具完成部署适合需要完成毕业设计或课程设计的在校学生也适合希望快速搭建人脸考勤系统原型的开发人员。压缩包共包含713个文件大小约267.69MB核心为307个Python源码文件涵盖Django框架的视图、模型、路由等后端模块前端部分包括样式、脚本与页面文件用于界面布局和交互效果另有数据库脚本、说明文档、答辩演示文稿等附件方便部署、查阅和答辩展示。目前已有92人浏览学习。资料内容完整包含前后端源码、数据库脚本、部署说明和答辩材料可直接部署运行也可作为二次开发的基础帮助深入理解目标检测与人脸识别在真实考勤场景中的集成方式。1. 一套python基于目标检测和人脸识别的企业考勤系统(django)标题拆开就是完整方案第一次在答辩现场见人演示刷脸打卡十个里有七八个会翻车有的是摄像头对不准脸有的是后台页面一直不刷新有的是明明打卡成功但 MySQL 里没记录。这个标题python基于目标检测和人脸识别的企业考勤系统(django)看着像一串关键词堆叠实际是一个标准的企业级毕设架构前端摄像头取流中间用目标检测锁住人脸位置再用识别算法比对员工特征最后把结果写进 MySQL由 Django 展示和管理。它适合两类人一是毕业设计抽中这类题目、想真正跑出一套系统而不是交代码了事的人二是刚学完 Django 和 OpenCV想看看两者怎么串成一个完整业务闭环的开发者。这套题最核心的不是某个模型有多强而是识别和业务两套系统怎么安稳地跑在一起。2. 先从标题看懂架构人脸识别怎么和企业考勤挂上钩2.1 目标检测和人脸识别为什么是两件事很多新手看这类项目时以为目标检测和人脸识别是同一个东西实际不是。目标检测是先在画面里回答哪里有人、哪里有脸输出的是坐标框人脸识别是拿到这块脸后回答这是谁。考勤链路如果只有人脸识别它会默认人脸已经摆在你面前但摄像头画面里往往有很多背景、侧脸、遮挡你必须先有目标检测把脸找出来再交给识别的部分做比对。这样做还有一个实际好处目标检测框出来的区域可以裁剪后单独做校正减少背景干扰识别率能提高不少。常见做法是YOLO 系列负责全图检测目标MTCNN、OpenCV DNN 或者 face_recognition 自带的人脸定位负责在检测框里精确定位脸部特征点。如果你用的是 YOLOv8 这类较新的目标检测模型训练集一般会包含 people 类别也可以直接把H人框交付给下一步。需要注意YOLO 检测到的人框不等于脸框企业考勤最终还是要落到人脸特征比对所以完整的代码里通常会有两级检测先锁人再锁脸。这套项目里的顺序我一般这样落地OpenCV 从摄像头逐帧读图拿到一帧后先做目标检测如果检测到可用的人脸区域就把这张脸裁出来转成编码向量再和 MySQL 里已经存好的员工特征库比对。整个过程不是一次性事务每一帧都可能识别失败所以程序设计上要有连续几帧都匹配同一个人才算打卡成功的防误判机制而不是单帧一比就写库。2.2 Django 在整个考勤链路里到底管什么Django 在这套系统里不是用来做人脸比对的它管的是业务层员工的新增与停用、考勤记录写入与查询、每日报表、平时的登录鉴权以及给识别端提供员工特征数据的接口。识别端通常是一个独立运行的服务或者是一个管理命令它去数据库里取员工照片和特征再在摄像头循环里逐帧处理。比较常见的目录组织是一个 Django 工程下建 accounts用户、employee员工管理、attendance考勤记录、face_recognition_service识别服务几个 app。识别服务里不依赖 Django 的 request/response只依赖 Django ORM 来读写 MySQL这样识别循环跑多久都不占 Web 端口Django 本身依然通过 runserver 给后台和管理员用。数据库连接上没什么特别玄学的Django 的 settings 里配好 MySQL 即可下面是这套系统里很常见的配置段DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: attendance_db, USER: root, PASSWORD: your_password, HOST: 127.0.0.1, PORT: 3306, OPTIONS: { charset: utf8mb4, autocommit: True, }, } }这段配置里几个参数是关键ENGINE 告诉 Django 使用 MySQL 后端NAME 是提前在 MySQL 里建好的空数据库名HOST 写成 127.0.0.1 时走 TCP 连接如果改成 localhost部分系统会走 socket 连接毕设环境里反而容易触发连接失败。OPTIONS 里的 charset 一定要给 utf8mb4因为员工姓名和备注可能有中文不指定时容易出现写入乱码和字符集报错。在真实项目里我还会在同一个 app 的init.py 里加上 PyMySQL 的兼容声明因为 Windows 环境编 mysqlclient 很痛苦PyMySQL 是更安稳的选择。配合 autocommit 后识别进程每写一条考勤记录都不需要手动 commit避免摄像头循环里偶发的事务悬挂。2.3 完整项目源码包里五个交付物怎么对应落地这套标题里写着完整项目源码mysql说明文档LWPPT其实这就是一次毕业设计答辩的全部交付。源码里至少有 Django 工程目录、识别算法模块和模板文件mysql 一般是一个 .sql 文件里面带建库建表语句和少量测试员工数据说明文档则告诉你环境版本、启动步骤是所有人解压后第一个该读的东西。LW 在大多数毕设包里指论文 Word 文档也就是你的设计报告里面包含系统流程图、数据库 E-R 图、功能模块说明和测试结果PPT 是答辩用的演示文稿。拿到这类压缩包后我建议按下面这张表逐个核对避免花半小时装环境却发现给的 requirements.txt 和代码对不上交付物包里通常对应什么落地时怎么核对项目源码Django 工程 识别脚本看有没有 manage.py 和 requirements.txtmysql数据库脚本或导出文件打开 .sql 看表名是否和 models 对应说明文档部署步骤、运行环境先看它使用的 Python/Django 版本LW论文 Word核对系统流程是否和源码功能一致PPT答辩演示文稿看演示页数和功能截图是否匹配通常我和学生一起做这类题时会先建一个 records 数据表里面保留 employee_id、clock_in_time、date、status 等字段然后才去调识别算法因为你识别得再准数据落不了库、后台查不到记录答辩时一样站不住脚。标题里但凡带了完整项目源码这种词真正值钱的地方就在这个数据闭环上而不是某个算法有多新。3. 复现的第一步把 Django 和 MySQL 环境跑起来3.1 用虚拟环境把依赖装齐重点照顾 face_recognition拿到代码后不要直接 pip install 到全局 Python 里毕设项目的依赖版本经常互相打架全局环境装坏是常有的事。第一步永远是建虚拟环境然后按照依赖清单安装。一个标准的起步命令集如下python -m venv venv # Windows 激活venv\Scripts\activate # Linux/mac 激活source venv/bin/activate pip install -r requirements.txt pip install opencv-python face_recognition pymysql如果包里没有 requirements.txt我一般会先装这几个核心依赖Django、mysqlclient 或 pymysql、opencv-python、numpy、face_recognition、dlib、pillow。其中 face_recognition 会自动拉取 dlibdlib 在 Windows 上常常需要 CMake 和 Visual Studio Build Tools 才能编译这是整套系统复现时最大的翻车点。常见的避坑替代方案是直接安装预编译的 dlib wheel或者改用 OpenCV 自带的人脸检测器来做特征点定位这样就能绕开编译一环。装完依赖后可以用一个很简单的命令确认人脸识别库能正常加载模型特征这样再往下做就不至于到摄像头环节才发现算法库根本没装上。python -c import cv2, face_recognition; print(cv2.__version__, face_recognition.__version__)这一步如果正常输出版本号说明 OpenCV 和 dlib 链路是通的。这里需要提醒的是face_recognition 首次调用会尝试加载预训练模型如果你的网络环境不允许它下载后续人脸编码会一直报错。所以我建议尽量在本地把模型准备好再启动识别服务。3.2 建 MySQL 库并让 Django 连上它在启动项目前要把数据库建出来运行下面这段 SQLCREATE DATABASE attendance_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER attendancelocalhost IDENTIFIED BY attendance123; GRANT ALL PRIVILEGES ON attendance_db.* TO attendancelocalhost; FLUSH PRIVILEGES;这里我把用户名和密码都写成项目专用账号而不是直接拿 root 跑是因为后面的识别服务需要长期连接数据库root 权限过大而且一旦密码泄露整个机器都暴露。项目账号只授权这一个库出问题也容易排查。CHARACTER SET 必须写成 utf8mb4否则后面存中文姓名、Excel 导出时都会出乱码。建完库之后回到 Django 项目的 settings.py把上一章那一段 DATABASES 配置填好。如果你是用 PyMySQL 连接还需要在项目同名目录的init.py 里加入这两行import pymysql pymysql.install_as_MySQLdb()这里的目的很直接Django 的 MySQL 后端在 Python 3 环境下默认去导入 MySQLdbPyMySQL 通过 install_as_MySQLdb 把自己伪装成 MySQLdb这样代码里不需要到处改连接方式。很多项目跑不起来根本不是代码问题而是这一步兼容没做报错信息是 ModuleNotFoundError: No module named MySQLdb。3.3 迁移数据库、创建 app、起后台下一步就是把 Django 自带的表结构同步到数据库。注意 migrate 只建表不建数据库本身数据库要先用 3.2 的 SQL 指令建好。顺序是先在项目根目录确认 manage.py 存在然后运行python manage.py startapp attendance python manage.py makemigrations attendance python manage.py migrate python manage.py createsuperuser python manage.py runserver这里用到了 Django 创建 app 的标准动作。startapp 会生成一个名叫 attendance 的 app 目录里面自动带上 models.py、views.py、admin.py。makemigrations 只生成迁移文件不写数据库真正把表建出来的是 migrate。createsuperuser 会提示输入用户名、邮箱和密码这是后面进 Django 管理后台用的超级管理员账号用户名不要用中文密码也别太简单答辩前忘了密码会很狼狈。跑完 runserver 后浏览器访问 http://127.0.0.1:8000/admin/能看到 Django 自带后台就说明 Web 层通了。真正要去的页面是 admin.py 里注册好的员工和考勤记录管理页。此时如果页面里出现表格相关报错说明有一张表没迁移上回去看 migrate 的输出往往是有个 app 的迁移文件没被包含进去。4. 把目标检测和人脸识别接进考勤流程最小可跑闭环4.1 摄像头取帧到人脸检测先写识别主循环识别端不一定要做成 Web 页面最可靠的做法是一个单独的 Python 脚本它通过 Django ORM 读取员工信息然后打开本地摄像头循环处理。下面的代码是这套系统里最核心的循环骨架import cv2 import face_recognition def run_camera(known_encodings): cap cv2.VideoCapture(0) if not cap.isOpened(): raise RuntimeError(无法打开摄像头) while True: ret, frame cap.read() if not ret: break rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) boxes face_recognition.face_locations(rgb, modelhog) encodings face_recognition.face_encodings(rgb, boxes) for box, enc in zip(boxes, encodings): # 后续比对逻辑 pass if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()这段循环里VideoCapture(0) 表示打开默认摄像头如果机器上有多个摄像头参数要换成 1 或 2。face_recognition.face_locations 是检测人脸位置modelhog 表示用 HOG 模型跑 CPU 检测速度较快但精度一般如果你有 GPU 或对精度要求高可以改成 modelcnn代价是每帧耗时明显增加。face_encodings 会在 boxes 的基础上把每张脸转为 128 维特征向量。整个 while 循环的频率不需要刻意控制因为 Hog 检测本身已经把帧率压到十几帧左右足够考勤使用。这里有个最常见的性能误区把 face_locations 和 face_encodings 同时放在循环里Python 的 GIL 会让 CPU 占用拉满。更稳的做法是把检测和识别拆到两个线程或者用队列把摄像头帧存起来识别线程慢慢消费。不过毕设阶段先跑通单线程再谈优化。4.2 员工特征库比对tolerance 阈值就是识别成败的命门把当前帧的脸编码好之后要和数据库里的员工特征做比对。face_recognition 库本身提供了现成函数但很多人对 threshold 参数的理解不够导致系统要么谁都认不出要么随便谁都能打卡。下面这段是稳定的比对片段def match_employee(unknown_encoding, known_dict): # known_dict: {employee_id: encoding} ids list(known_dict.keys()) known_encodings [known_dict[i] for i in ids] distances face_recognition.face_distance(known_encodings, unknown_encoding) best_idx int(distances.argmin()) if distances[best_idx] 0.45: return ids[best_idx], distances[best_idx] return None, None这里没有用 compare_faces而是直接用 face_distance。compare_faces 返回的是 True/False 列表它内部靠 tolerance 判断默认值是 0.6在考勤场景里太宽松经常出现两个人同时被识别成同一个人。face_distance 会给出具体的距离值距离越小越像。0.45 是我在真实项目里常用的一个起步值如果你发现识别率太低把它升到 0.5如果发现不同员工互相误认就往 0.4 降。这个参数没有普适值不同摄像头、不同光照下要重新测。员工特征从哪来一般是在 Django 后台或者一个管理命令里遍历员工照片文件用 face_encodings 得到 128 维向量后存到 Employee 表的 bloat 字段或单独一张表里。我建议单独建 face_feature 表一员工一行字段不要把它塞在比较大的业务表里因为识别进程每次启动都要全量加载一遍特征向量字段隔离后加载速度会快得多。4.3 打卡记录写库用 ORM 查询和删除保证不重复比对成功只能说明脸对上了接下来这步是把考勤记录写进 MySQL。这里必须处理重复打卡的问题否则同一人在摄像头前多站几秒表里就会多出好几条记录。纯 SQL 能写但 Django ORM 更直观。常见逻辑是先查今天的记录是否存在不存在才新增from django.utils import timezone from attendance.models import AttendanceRecord, Employee def mark_attendance(employee, nowNone): now now or timezone.now() today now.date() exists AttendanceRecord.objects.filter( employeeemployee, datetoday ).exists() if exists: return False AttendanceRecord.objects.create( employeeemployee, datetoday, clock_in_timenow.time(), statusnormal ) return True这段代码先查询后写入两个动作放在同一个事务里更安全。在 Django 里给函数加 transaction.atomic 装饰器可以保证查询和创建中间不会插进别的事务。打卡成功返回 True前端可以弹出打卡成功的提示。如果录错了要撤销用 Django ORM 执行删除操作也很简单只需执行 AttendanceRecord.objects.filter(employeeemployee, datetoday).delete()。真正的细节在时间上。考勤系统的 date 应该取本地日期timezone.now() 里如果 settings 里 TIME_ZONE 没配对可能出现在凌晨打卡时算成前一天日期的问题这是非常典型的时间边界坑。TIMESTAMP 字段会自动跟随时区而 DATE 字段不会所以设计表结构时建议用 date 字段保存日期用 time 字段保存打卡时刻两者都由 Django 代码生成的本地日期来填充。5. 毕业设计避坑从环境到演示现场最容易翻车的五个点所有科目里考勤系统算是最容易出事故的演示项目因为摄像头、光线、后台、数据库环环相扣任何一个环节失效现场都能肉眼可见地丢人。以下五条是我带做这套题目时几乎每次都会碰到的坑全都按现象、原因、解决写清楚。5.1 Windows 下安装 dlib 编译报错现象pip install dlib 或安装 face_recognition 时终端刷屏一堆 CMake 编译错误半小时后失败。原因dlib 默认走源码编译Windows 上缺 C 工具链部分版本还缺 CMake。解决换用预编译 wheel 包安装对应 Python 版本的 dlib 离线包或者干脆不用 face_recognition改用 OpenCV 的 DNN 人脸检测加人脸编码模型。对毕设来说效果差不大重点是稳定。另一种方案是装 Visual Studio Build Tools再装 CMake但我不会为一个演示项目去赌编译运气。5.2 MySQL 连接报 2002 或 SSL 错误现象启动 Django 或识别服务时报错 Cant connect to local MySQL server through socket 或 SSL connection error。原因HOST 配置为 localhost 时MySQL 驱动走 socket 连接而大多数本地环境只开放了 TCP 3306SSL 错误则是驱动默认要求加密连接但本地 MySQL 没启用。解决DATABASES 里 HOST 改成 127.0.0.1并在 OPTIONS 里显式关闭 SSL也就是加入 ssl: {disabled: True}。这两个配置一改绝大多数连接问题会消失。如果还连不上用 Navicat 测试同一账号能否连接能连就说明代码配置问题不能连则是 MySQL 侧问题优先查账号权限。5.3 模板里渲染不出员工照片或识别框现象后台页面有员工头像位置但是图片显示为破图或者前端页面上识别框一直没出现。原因Django 默认只处理和渲染静态文件的 static 目录你把照片放进了一个没有被挂载的目录摄像头画面画框则是 OpenCV 窗口在服务端弹出来了根本没传到网页。解决照片统一放在项目根的 static/employee_photos/ 下并在 settings 里确认 STATIC_URL 和 STATICFILES_DIRS 指向正确。识别框要显示在网页上的话最快是用 VideoCapture 把每一帧处理后 push 到前端常见做法是 Flask 或 Django 视图源源不断输出 JPEG 流。体面一点的做法是接入 Django Channels 走 WebSocket 推送但毕设没必要直接用轮询拉帧最省事。5.4 识别成功率太低换个人也能打卡现象本人站在摄像头前识别失败换一个姓名完全不同的人居然显示识别成功。原因对比阈值太宽0.6 的默认值本来就是给人脸解锁设计的写在考勤里会很松另外是员工照片只有一张特征向量没有覆盖不同角度。解决改成 face_distance 后把阈值收到 0.45 左右然后现场拉一个 10 人测试集把阈值从 0.4 到 0.5 逐个测一遍画出正确率曲线再定值。这个步骤听起来很玄学其实都是数据说话。条件允许的话给每个员工录入正脸和左右侧脸三张照片特征取平均或者存三个向量任何一张匹配即算通过。5.5 演示时反复打卡刷出多条记录现象一个人在摄像头前待了十秒后台考勤表里出现八条记录。原因写记录时没做同一天已有记录就跳过的判断或者识别进程在重复执行 mark_attendance 时查到的结果每次都是不存在。解决在 mark_attendance 外层加唯一约束也就是 MySQL 表里给 employee_id date 建 unique index同时代码里保留 ORM 查询判断逻辑。唯一索引是最后一道防撞墙即使两个线程同时跑数据库层也会拦下第二条插入。演示时清掉当天的测试记录用前面说过的 objects.filter().delete() 一键清空即可。6. 答辩前怎么验证这套系统真的能撑住而不只是能启动6.1 用同一组照片跑一个可量化的冒烟测试别等到答辩现场才第一次开摄像头。我会在演示前写一个很短的脚本读取 10 张测试照片循环执行检测人脸、比对、写记录三个动作统计识别成功率和平均耗时。这个脚本能同时验证算法链路、数据库写入和业务字段是否正确。核心逻辑如下import time import face_recognition from attendance.services import mark_attendance from attendance.models import Employee def smoke_test(photo_paths): ok 0 for path in photo_paths: image face_recognition.load_image_file(path) boxes face_recognition.face_locations(image) if not boxes: continue enc face_recognition.face_encodings(image, boxes)[0] emp, dist match_employee(enc, Employee.load_encodings()) if emp and mark_attendance(emp): ok 1 time.sleep(0.2) print(fpass rate: {ok}/{len(photo_paths)})每个参数都有意义sleep(0.2) 模拟摄像头逐帧间隔确保不出现大量并发写入load_encodings 是我在 Employee 模型里定义的一个方法把全库员工特征提前加载成字典避免循环里每条都查数据库。对识别结果我一般不追求 100% 通过正常光照下 80% 以上就可以上演示但数据库写入必须是 100% 不重复。6.2 现场演示的三个习惯性动作我自己的习惯是演示前把摄像头识别降到最低分辨率和帧率因为教室投影或会议室的光照通常偏暗硬要跑 1080p 会卡成幻灯片反而不如 640×480 流畅。第二准备好两张员工测试照片放到桌面万一摄像头在现场被占用或驱动闪退立刻切到图片模式页面依然能展示完整的检测和打卡流程。第三演示前把考勤表清空并给数据库做个备份这样随时能重新开始演示不留下之前测试的脏数据。这三个动作能解决 80% 的现场翻车剩下的就别硬扛大方地说是光线问题展示后端数据补录的流程反而更容易拿分。这套题做到最后你会发现真正花时间的不是模型而是把检测到人、认出来、写进库、后台看得到这个闭环打磨得不出错。希望这些从环境到现场的细节能帮到正在为这套项目头疼的人。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站