Django人脸识别门禁系统:从活体检测到权限控制的完整实现
2026/9/16 19:23:08 网站建设 项目流程

简介:本资源是一套基于Python与Django框架实现的人脸识别门禁管理系统源码,专为计算机类专业本科生毕业设计、课程设计及项目实战学习者打造,切实解决身份核验、权限管控与系统集成等实际工程问题。压缩包共2001个文件,主体为1668个Python后端逻辑与算法模块、124个HTML前端页面、89个JavaScript交互脚本,辅以CSS样式、XML配置、JSON数据及少量C/fortran扩展文件(如gfortran_vs2003_hack.c),完整覆盖前后端开发、模型调用与部署适配环节,总大小417.25MB。目前已有618人学习下载,资源经导师指导并高分通过答辩,所有模块均严格调试可直接运行。使用者可获得完整的Django项目结构、人脸识别流程封装(含OpenCV/face_recognition集成)、用户权限分级管理、门禁日志记录与Web可视化界面,以及配套的README说明与基础部署文档,适合毕设快速落地与技术原理深度复现。

1. 这不是个“调用API就完事”的人脸识别项目,而是一套可部署、可调试、能过答辩的完整门禁业务闭环

很多同学拿到“人脸识别门禁”毕设资源,第一反应是找 OpenCV + face_recognition 库读摄像头、比对特征值——结果跑通 demo 后卡在「怎么和用户账号绑定」「考勤记录存哪」「管理员后台怎么改权限」「断网时还能不能开门」这些真实业务环节。这个 Django 项目恰恰绕开了玩具式 demo 的陷阱:它把人脸注册、活体检测(基于帧差+眨眼动作)、门禁设备联动(模拟串口指令与状态反馈)、权限分级(访客/员工/管理员)、操作日志审计、Web 管理后台全链路打通。代码结构清晰,models.py 里Person,AccessRecord,Device三张核心表关系明确;views.py 按业务域拆分(face_register,access_control,admin_dashboard);templates 中 admin 界面已重写为响应式布局,连select2.min.csswidgets.css都已集成。适合计算机/软件工程专业学生直接用于毕业设计,也适合作为 Django Web 开发与 CV 工程交叉实践的入门锚点。


2. 从环境初始化到人脸注册流程:Django 项目启动与核心业务模块验证

2.1 环境依赖与 Python/Django 版本兼容性确认

该项目基于 Python 3.8+ 与 Django 3.2 LTS 构建(非 Django 4.x 或 5.x),这是关键前提。高版本 Django 对中间件、URL 路由语法、模板引擎有 Breaking Change,强行升级会导致admin页面白屏、staticfiles加载失败。验证方式如下:

# 检查当前 Python 版本(必须 ≥3.8) python --version # 创建隔离虚拟环境(推荐使用 venv,避免污染系统环境) python -m venv venv_face source venv_face/bin/activate # Linux/macOS # venv_face\Scripts\activate.bat # Windows # 安装指定版本 Django 及必要扩展 pip install "Django==3.2.23" djangorestframework opencv-python-headless face-recognition numpy pillow python-dotenv # 验证安装 python -c "import django; print(django.get_version())" # 输出应为 3.2.23

注意face-recognition库底层依赖dlib,在 Windows 上需预装 Visual Studio Build Tools;Linux 用户建议用apt-get install build-essential libx11-dev libatlas-base-dev libgtk-3-dev libboost-python1.71-dev补齐编译工具链。若pip install face-recognition失败,可改用pip install face-recognition==1.3.0(该版本对 dlib 兼容性更稳定)。

2.2 数据库迁移与初始超级用户创建

项目使用 SQLite 作为默认数据库(开发友好),但settings.py中已预留 MySQL 配置入口。首次运行前必须完成迁移:

# 进入项目根目录(含 manage.py 的位置) cd /path/to/your/unzipped/project/ # 执行数据库迁移(生成 auth, contenttypes, sessions 等内置表 + 自定义 models) python manage.py migrate # 创建超级用户(用于登录 admin 后台) python manage.py createsuperuser # 按提示输入用户名、邮箱(可选)、密码(两次输入) # 示例:Username: admin | Email address: admin@example.com | Password: ********

迁移成功后,db.sqlite3文件将生成,其中包含auth_user,face_person,face_accessrecord,face_device等表。可通过sqlite3 db.sqlite3 ".tables"快速验证。

2.3 启动服务并完成首个人脸注册

启动开发服务器:

python manage.py runserver 0.0.0.0:8000

访问http://127.0.0.1:8000/admin/,用上一步创建的 superuser 登录。进入FacePersons,点击右上角ADD PERSON

  • Name: 张三
  • Employee ID: EMP001
  • Department: 技术部
  • Photo: 上传一张正脸清晰证件照(JPG/PNG,建议 300×400 像素)
  • Status: Active

保存后,系统自动触发face_recognition提取该图像的 128 维特征向量,存入face_person.embedding字段(BLOB 类型)。此过程耗时约 1.2~2.5 秒(取决于 CPU 性能),不是调用云端 API,所有计算在本地完成

提示:若注册时报错Unable to get facial landmarks,说明上传图片中人脸未被检测到。请确保照片为正面、无遮挡、光照均匀、人脸占画面 1/3 以上。可先用cv2.imshow()在本地测试face_recognition.face_locations()是否返回坐标。

2.4 模拟门禁通行:通过 Web 接口触发识别与权限校验

项目提供/api/verify/接口接收 base64 编码的实时帧图像,返回{ "status": "granted", "person": "张三", "timestamp": "2024-06-15T14:22:35Z" }或拒绝响应。测试方法:

# 使用 curl 模拟摄像头上传(需准备 test.jpg) curl -X POST http://127.0.0.1:8000/api/verify/ \ -H "Content-Type: application/json" \ -d '{"image": "'"$(base64 -i test.jpg | tr -d '\n')"'"}'

后端逻辑位于face/views.pyFaceVerificationView.post()方法:

  1. 解码 base64 图像 →np.frombuffer(..., dtype=np.uint8)cv2.imdecode()
  2. 调用face_recognition.face_locations()定位人脸区域
  3. 若检测到多人脸,取最大面积框;无人脸则返回{"status": "no_face"}
  4. 提取特征向量,与数据库中所有Person.embedding计算欧氏距离
  5. 距离 < 0.6 判定为匹配(阈值在face/utils.pyFACE_DISTANCE_THRESHOLD = 0.6可调)
  6. 校验Person.status == 'Active'Person.department在允许通行区域列表中(权限控制点)

该流程完全复现了真实门禁系统的“识别-比对-授权-记录”四步闭环,而非仅展示识别结果。


3. 权限控制与设备联动:理解门禁业务逻辑在 Django 中的落地实现

3.1 基于 Group 和 Permission 的细粒度权限模型

Django 内置的auth.Groupauth.Permission被深度整合进门禁业务。项目定义了三个核心 Group:

Group 名称关联 Permission典型操作
SecurityStaffCan view accessrecord,Can change device查看所有通行记录、重启门禁设备
DepartmentAdminCan add person,Can change person为本部门员工注册人脸、更新信息
VisitorCan view own accessrecord仅查看自己来访记录

创建方式(在 admin 后台或 shell 中):

# python manage.py shell from django.contrib.auth.models import Group, Permission from django.contrib.contenttypes.models import ContentType from face.models import Person, AccessRecord # 获取 Person 模型的 content_type person_ct = ContentType.objects.get_for_model(Person) # 创建 DepartmentAdmin 组并赋予权限 dept_admin = Group.objects.create(name='DepartmentAdmin') dept_admin.permissions.add( Permission.objects.get(codename='add_person', content_type=person_ct), Permission.objects.get(codename='change_person', content_type=person_ct) )

注意Visitor组的权限通过AccessRecord模型的owner字段实现行级控制(def has_object_permissionface/permissions.py中重写),而非单纯靠 Group。这是避免“访客看到他人记录”的关键设计。

3.2 Device 模型与串口指令模拟机制

face/models.pyDevice模型定义了门禁硬件抽象:

class Device(models.Model): name = models.CharField(max_length=100) # 设备名称,如 "东门主闸机" ip_address = models.GenericIPAddressField(null=True, blank=True) # 可选网络地址 serial_port = models.CharField(max_length=20, default='/dev/ttyUSB0') # 串口路径 status = models.CharField(max_length=20, choices=[('online', '在线'), ('offline', '离线')]) last_heartbeat = models.DateTimeField(auto_now=True) def open_door(self): """模拟发送串口指令开门(实际项目需对接 pyserial)""" import time # 此处替换为真实串口通信代码 print(f"[{self.name}] Sending OPEN command to {self.serial_port}") time.sleep(0.3) # 模拟指令传输延迟 return True

face/views.pyDeviceControlView接收/api/device/<id>/open/请求,调用device.open_door()并记录AccessRecord项目未硬编码串口驱动,而是留出open_door()方法供二次开发接入真实硬件(如 RS485 门禁控制器、Wiegand 协议读卡器)。

3.3 AccessRecord 日志的完整性与审计价值

每次通行都会生成一条AccessRecord记录,字段设计直指审计需求:

字段类型说明
personForeignKey to Person关联注册人员,支持外键查询
deviceForeignKey to Device明确通行位置,便于统计各闸机负载
timestampDateTimeField(auto_now_add=True)精确到毫秒的时间戳,不可篡改
resultCharField(choices=[('granted','放行'),('denied','拒绝'),('timeout','超时')])结果分类,支持按状态筛选
confidenceFloatField(null=True)识别置信度(欧氏距离倒数),用于优化阈值
image_previewImageField(upload_to='records/')存储识别时刻抓拍图,原始证据留存

在 admin 后台,AccessRecord列表页已启用list_filter(按device,result,timestamp__date),支持导出 CSV(actions = ['export_as_csv']),满足毕设答辩中“数据可追溯、过程可验证”的硬性要求。


4. 活体检测与性能调优:让识别在真实光照与角度下依然可靠

4.1 基于帧差与眨眼检测的轻量活体判断

单纯比对静态照片特征极易被照片/视频欺骗。本项目在face/utils.py实现两级活体检测:

  1. 帧差运动检测:连续 3 帧图像灰度化后做差分,计算运动像素占比。若 < 5%,判定为静止图像(可能为照片)。
  2. 眨眼频率检测:使用dlib的 68 点面部关键点,计算 EAR(Eye Aspect Ratio)值。连续 2 秒内眨眼次数 ≥ 2 次视为活体。

核心代码逻辑(简化版):

# face/utils.py def is_living_face(frame_sequence): """ frame_sequence: List[np.ndarray], 至少包含 5 帧连续图像 返回 bool: True 表示通过活体检测 """ # Step 1: 帧差运动检测 motion_ratio = calculate_motion_ratio(frame_sequence) if motion_ratio < 0.05: return False # Step 2: 眨眼检测(需 dlib predictor) blink_count = 0 for frame in frame_sequence[-3:]: # 取最后3帧分析眨眼 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) faces = detector(gray) for face in faces: shape = predictor(gray, face) left_eye = shape_to_np(shape)[36:42] # 左眼6点 right_eye = shape_to_np(shape)[42:48] # 右眼6点 ear_left = eye_aspect_ratio(left_eye) ear_right = eye_aspect_ratio(right_eye) if (ear_left < 0.2 or ear_right < 0.2): # EAR < 0.2 视为闭眼 blink_count += 1 break return blink_count >= 2

参数说明EAR计算公式为(A+B)/(2*C),其中 A/B 为上下眼睑距离,C 为左右眼睑距离。阈值0.2经实测在多数光照下稳定有效;motion_ratio < 0.05可过滤手机屏幕翻拍等低运动场景。

4.2 识别速度优化:特征向量缓存与批量比对

原始face_recognition.compare_faces()对 N 个人逐个计算距离,O(N) 时间复杂度。项目改用scipy.spatial.distance.cdist批量计算,将耗时从 120ms(N=50)降至 18ms:

# face/models.py 中 PersonManager def bulk_compare_embeddings(self, unknown_embedding): """批量比对未知特征向量与所有激活人员""" active_persons = self.filter(status='Active').values_list('id', 'embedding') if not active_persons: return [] ids, embeddings = zip(*active_persons) # 将 BLOB 字段反序列化为 numpy array known_embeddings = np.array([np.frombuffer(e, dtype=np.float64) for e in embeddings]) # 批量计算欧氏距离 distances = cdist([unknown_embedding], known_embeddings, metric='euclidean')[0] # 返回 (id, distance) 元组列表,按距离升序 return sorted(zip(ids, distances), key=lambda x: x[1])

此优化使单次识别响应时间稳定在 80~150ms(i5-8250U),满足门禁系统“亚秒级响应”要求。

4.3 光照与角度鲁棒性增强技巧

face/views.pyFaceVerificationView中,预处理阶段加入两项关键增强:

def preprocess_frame(frame): # 1. 直方图均衡化提升暗部细节(应对背光/弱光) gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) enhanced = clahe.apply(gray) # 2. 自适应伽马校正解决过曝(如正午阳光直射) mean_brightness = np.mean(enhanced) gamma = 0.7 + (mean_brightness / 255.0) * 0.6 # gamma ∈ [0.7, 1.3] inv_gamma = 1.0 / gamma table = np.array([((i / 255.0) ** inv_gamma) * 255 for i in np.arange(0, 256)]).astype("uint8") corrected = cv2.LUT(enhanced, table) return cv2.cvtColor(corrected, cv2.COLOR_GRAY2BGR)

实测表明,该组合可将侧脸(±30°)、半侧光、逆光场景下的识别率从 62% 提升至 89%(测试集 200 张难例图像)。


5. 部署与答辩准备:从本地调试到演示环境的一站式 checklist

5.1 生产环境部署关键配置项

项目已预置production.py配置文件(位于face/settings/),需在部署时启用:

# 启用生产配置 export DJANGO_SETTINGS_MODULE=face.settings.production python manage.py collectstatic --noinput # 收集静态文件到 STATIC_ROOT python manage.py runserver 0.0.0.0:8000 # 仅测试,正式环境用 Gunicorn+Nginx

production.py中必须修改的 4 项:

配置项值示例说明
DEBUG = FalseFalse关闭调试模式,禁用敏感信息输出
ALLOWED_HOSTS['your-domain.com', '192.168.1.100']严格限制访问域名/IP,防止 Host Header 攻击
STATIC_ROOT'/var/www/face/static/'Nginx 静态文件服务路径
DATABASES['default']['PASSWORD']'your_mysql_password'若切换 MySQL,此处填真实密码

提示:SQLite 不适用于生产环境。切换 MySQL 时,需执行pip install mysqlclient并确保系统已安装libmysqlclient-dev(Ubuntu)或mysql-devel(CentOS)。

5.2 答辩演示脚本与故障预案

为保障答辩现场流畅,建议准备以下 3 个最小可行演示单元:

场景操作步骤预期结果故障应对
人脸注册Admin 后台 → Add Person → 上传张三照片face_person表新增记录,embedding字段非空若失败,提前截图db.sqlite3中该记录的embedding字段十六进制值证明已提取成功
实时识别访问/demo/页面 → 点击“开始识别” → 对准摄像头页面显示“张三 已放行”,AccessRecord新增一条记录若摄像头权限问题,改用curl测试/api/verify/接口,附带test.jpgbase64
权限验证用访客账号登录 → 尝试访问/admin/face/person/返回 403 Forbidden 页面若权限未生效,检查face/permissions.pyVisitorPermission是否正确继承BasePermission

5.3 毕设报告中必体现的技术亮点表格

在论文“系统实现”章节,建议用下表突出技术深度(避免罗列功能,聚焦实现差异):

技术点本项目实现常见毕设误区价值说明
活体检测帧差运动 + 眨眼频率双因子判断仅用单帧照片比对,无防伪机制通过答辩专家“安全性”质询的关键证据
权限模型Group + Object-level Permission 混合控制全局 superuser 或硬编码 if-else体现对 Django 认证体系的深度理解
识别性能cdist批量比对 + 特征向量缓存逐个compare_faces()循环支撑“实时性”指标,答辩时可展示压测数据
部署适配production.py预置安全配置 + MySQL 切换指南仅能在DEBUG=True下运行展示工程化思维,非玩具项目

最后一行不总结。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询