尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于人脸识别与步态识别的智能门禁系统设计与实现

基于人脸识别与步态识别的智能门禁系统设计与实现 简介基于人脸识别与步态识别的智能门禁系统是一份计算机视觉方向的毕设/课设源码包附带系统说明文档面向计科、人工智能、数据科学等专业在校生及开发人员。项目借助Python及开源视觉库实现人脸、步态双重生物特征认证从前端交互、后端服务到数据库模块覆盖完整业务流程既能用于毕设答辩与课程设计也适合作为入门进阶和二次开发底稿。压缩包共524个文件体积约140.63MB以TypeScript、Vue、Java等前后端源码为主同时包含大量PNG/JPG图片、MP4演示视频以及SQL、Shell等资源与脚本目录分类清楚便于按模块检索查阅。说明文档配合完整可运行代码可帮助快速部署环境并理解识别流程目前已有332人学习下载适合在此基础上扩展门禁控制、告警联动等个性化功能。 又到了一年一度的毕设选题季后台不少同学来问我“计算机视觉方向的课设做什么好”。如果你正在为选题发愁或者已经选了一个CV方向却不知道从哪下手那我强烈建议你看看“基于人脸识别步态识别的智能门禁系统”这个方向。这个题目我从大三课设一直跟到毕业设计前后迭代过三版Python源码加文档的思路非常成熟几乎涵盖了计算机视觉入门的全部核心技能点。人脸识别解决“你是谁”步态识别解决“你是不是本人且处于正常状态”两者结合做出一个真正能跑起来的门禁系统既能应对毕设答辩也能作为简历上的项目亮点。这篇文章我会把整个项目的设计思路、核心模块实现、实操过程中踩过的坑全部摊开讲帮你少走弯路。1. 项目整体设计人脸步态双模态门禁的思路拆解1.1 为什么选人脸步态这个组合先说个最简单的逻辑。单独做一个人脸识别门禁市面上方案太多了答辩老师一眼就能看出难度天花板。如果你只交一个人脸识别大概率会被问“你这个和手机人脸解锁有什么区别”。但加上步态识别整个项目的技术含量就完全不一样了。人脸识别本质上是静态的、近距离的、需要配合的识别方式。它有几个致命弱点光线不好时准确率直线下降戴口罩帽子直接失联更别提有人拿一张照片就能骗过普通摄像头。而步态识别是动态的、远距离的、不需要配合的识别方式走路的姿态、节奏、摆臂幅度、步幅大小这些特征很难伪装也很难被照片视频攻击。两者结合起来正好形成互补——一个管近距离验证一个管远距离感知。从毕设评分角度来说这个组合也很有优势。它天然就是一个“多模态生物识别系统”的完整案例有算法、有工程、有数据、有界面还能延伸到活体检测和安防应用写说明文档的时候可说的点特别多。1.2 系统整体架构与识别流程整个系统我最终使用的是Python 3.8 OpenCV dlib face_recognition MediaPipe PyQt5的组合方案整体工作流拆成两条识别链路再加一个决策层。人脸识别链路摄像头实时帧 - OpenCV读取 - dlib HOG人脸检测 - 人脸对齐 - face_recognition提取128维特征向量 - 与数据库特征比对 - 输出相似度和身份。步态识别链路视频流连续帧 - MediaPipe Pose提取人体33个关键点 - 选取髋、膝、踝等下肢关节点 - 计算关节角度和步态周期 - 生成步态特征序列 - 与注册的步态特征比对 - 输出相似度和身份。决策层拿到两条链路的结果之后采用“人脸为主、步态兜底”的融合策略。近距离就靠人脸直接Bingo人脸质量太差或者置信度不够时立刻切到步态识别去验。两条链路都失败则拒绝通行。整个过程通过PyQt5做一个控制面板实时显示画面、识别结果、门禁状态和通行记录。1.3 技术选型为什么是这套Python生态说句实在话用Python做CV毕设最大的优势根本不是性能而是调试效率。人脸识别我用的是face_recognition库它底层封装的是dlib的ResNet模型能把人脸编码成128维的浮点向量。这个库最大的好处是API极简几行代码就能完成特征提取和比对非常适合在毕设时间紧的情况下快速出一个稳定可用的效果。如果你从零开始训练一个自己的人脸识别模型光是准备数据集和调参就够你吃一壶的。步态识别部分我用的是MediaPipe Pose而不是OpenPose。原因很简单MediaPipe是Google出的在CPU上就能跑实时推理TensorFlow Lite优化做得非常好而且pip install mediapipe一条命令搞定。OpenPose精度确实高一点但环境配置复杂对毕设来说性价比太低。1.4 项目目录结构与交付物我的最终交付物包括完整的Python源码、系统说明文档、演示视频和测试数据集。源码目录大致是smart_access_control/ ├── main.py # 系统主入口PyQt5界面 ├── face_module/ │ ├── face_register.py # 人脸注册模块 │ ├── face_recognizer.py # 人脸识别与比对模块 │ └── face_utils.py # 人脸检测对齐等工具函数 ├── gait_module/ │ ├── gait_register.py # 步态注册模块 │ ├── gait_recognizer.py # 步态识别模块 │ └── pose_utils.py # 骨架点提取与角度计算 ├── database/ │ ├── db_manager.py # SQLite数据库管理 │ └── feature_cache.py # 特征缓存 ├── ui/ │ ├── main_window.py # 主界面 │ └── register_dialog.py # 注册弹窗 ├── data/ │ ├── registered/ # 注册用户数据 │ └── logs/ # 通行记录 └── docs/ └── 系统说明文档.docx2. 人脸识别模块从检测到比对的完整链路2.1 人脸检测与对齐人脸检测是人脸识别的第一步目的就是从画面里把人的脸框出来。这里我踩过一个坑一开始用的是OpenCV自带的Haar Cascade检测器速度快是快但正脸稍微偏一点或者光线暗一点就直接检测不到到了答辩演示的时候特别尴尬。建议直接用dlib的HOG Linear SVM检测器它比Haar Cascade稳定很多对姿态和光照的容忍度都更好。如果你追求极致准确率可以用MTCNN但速度会慢不少。毕设场景用dlib足够了。人脸检测之后还有一个容易被忽略的步骤人脸对齐。人脸对齐就是把检测到的人脸根据眼睛等关键点位置做旋转归一化让所有的脸都处于一个标准姿势。face_recognition库里封装了face_landmarks接口可以拿到眼睛坐标再用仿射变换把人脸校正到统一位置。这一步不做的话同一个人的脸稍微歪一点识别率就会明显下降。2.2 特征提取与128维向量比对核心代码其实就这几行import face_recognition # 加载图片并提取128维人脸特征向量 image face_recognition.load_image_file(person.jpg) face_locations face_recognition.face_locations(image) face_encoding face_recognition.face_encodings(image, face_locations)[0] # 与数据库中人脸特征比对计算欧氏距离 def match_face(unknown_encoding, db_encodings, threshold0.45): distances face_recognition.face_distance(db_encodings, unknown_encoding) min_idx np.argmin(distances) if distances[min_idx] threshold: return min_idx, distances[min_idx] return None, None这里的阈值0.45是个经验值我自己测下来比较稳。face_recognition自带的compare_faces函数默认阈值是0.6听起来很宽松但实际上0.5~0.6之间已经会出现不少误识别了。实测同一人不同光照下距离通常在0.25~0.4之间不同人通常在0.5以上。具体阈值建议你用自己采集的数据跑一遍ROC曲线再定选在误识率和拒识率交叉点附近。2.3 人脸识别实操中的4个隐藏坑第一个坑是注册照片的质量。很多同学拿手机随便拍一张就录入系统结果在摄像头下一识别一个不通过。注册照片最理想的是正脸、平视、光线均匀、无遮挡分辨率不要太低。我在文档里专门加了一个注册质量检测模块检测到模糊或者侧脸会直接提示重新采集。第二个坑是摄像头帧率问题。OpenCV默认读取的视频流是30fps但如果直接对每一帧都跑一次dlib检测加特征提取CPU马上被打满。我的做法是做帧间隔检测每5帧做一次人脸检测检测到人脸之后在后续帧里用追踪器锁定人脸区域只有追踪失败才重新检测。这样CPU占用能降到原来的三分之一左右。第三个坑是光照的影响。教室、实验室的灯光往往偏黄或者偏暗我在预处理阶段加了一个简单的直方图均衡化对灰度图做CLAHE对比度受限自适应直方图均衡效果非常明显人脸特征提取的稳定性提升了一个档次。第四个坑是活体检测。如果答辩老师问“拿一张照片能不能骗过系统”你得有应对方案。最简单的做法是要求用户完成一个随机动作比如眨眨眼、摇摇头通过检测眼睛纵横比或者头部姿态变化来判断是不是活体。这个方案不用深度学习模型实现难度低但足以应付大部分场景。3. 步态识别模块难度高出预期3.1 步态识别的两条技术路线步态识别是这个项目里最有含金量的部分也是最容易翻车的部分我会讲得细一点。学术界步态识别主流有两类方法基于外观的方法和基于模型的方法。基于外观的方法用步态能量图GEIGait Energy Image作为特征。简单说就是在一个步态周期内把人的二值轮廓图像叠加平均得到一张“影子图”。这张图上包含了一个人的体型、走路姿势、摆动幅度等信息然后用CNN或者直接算相似度来做识别。GEI的好处是对轮廓噪声不敏感缺点是视角变化大时效果很差。基于模型的方法则是先提取人体骨架关键点再计算关节角度、步频、步幅等几何特征。这里我选的是基于模型的方法用的是MediaPipe Pose提取33个关键点。原因有二一是MediaPipe在普通笔记本CPU上就能跑到30fps二是骨架特征比轮廓特征更直观可控出了问题好排查对写文档也很友好。3.2 MediaPipe骨架点提取与步态特征构建MediaPipe Pose的使用非常简单import cv2 import mediapipe as mp mp_pose mp.solutions.pose pose mp_pose.Pose(static_image_modeFalse, min_detection_confidence0.5) cap cv2.VideoCapture(0) while cap.isOpened(): ret, frame cap.read() rgb_frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) results pose.process(rgb_frame) if results.pose_landmarks: # 拿到左髋、左膝、左踝的坐标 hip results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_HIP] knee results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_KNEE] ankle results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_ANKLE] # 计算膝关节角度 angle calculate_angle(hip, knee, ankle)骨架点提取只是第一步怎么把这些点变成能区分人的特征才是核心问题。我自己构建的特征向量包含三个维度时序角度特征、步态周期特征、静态比例特征。时序角度特征就是髋关节、膝关节在下肢摆动过程中的角度变化序列步态周期特征是步频和步幅静态比例特征就比较直白了——身高、腿长占身高的比例、肩宽等等。这里要说明一个关键点步态识别不是单一时刻的姿态而是连续帧之间姿态变化的序列所以你一定要保住时序信息不要拿单帧去匹配。3.3 步态周期检测与动态时间规整匹配步态周期检测我用的方法是跟踪两条腿的膝关节角度变化定义左腿和右腿角度差值的过零点作为一个步态周期的边界。这样就能把一个连续行走视频切成一帧一帧完整的“走路单元”每个单元代表一个完整的两步循环。切好周期后问题来了不同人走路快慢不一样导致特征序列的长度不一样直接算欧氏距离是不行的。解决办法是用动态时间规整DTWDynamic Time Warping算法。DTW的思想比较简单它允许两个序列在时间轴上“拉伸”或“压缩”来对齐然后计算对齐后的累积距离。对于步态这种天然存在速度差异的信号DTW比直接逐帧对比靠谱得多。代码实现大概长这样import numpy as np from scipy.spatial.distance import euclidean from fastdtw import fastdtw # 把多段角速度序列拼成特征序列 gait_feature_seq build_gait_sequence(frame_angles) # 与参考序列做DTW匹配fastdtw是加速版DTW distance, path fastdtw(gait_feature_seq, ref_feature_seq, disteuclidean) similarity 1.0 / (1.0 distance)DTW匹配的效果和序列长度有直接关系。我测过取12帧左右的半周期做匹配效果相对稳定太长反而会引入不必要的噪声。另外提醒一句fastdtw是近似算法跑得比标准DTW快精度损失在毕设场景可以接受。3.4 步态识别避坑指南步态识别最大的敌人是视角和着装。同一个人的步态从正面录和从侧面录特征差别非常大。我的方案是在注册阶段同时录入正、侧两个视角的步态样本识别时也尽量要求用户在摄像头前走一个固定路线。着装方面宽松裤子和大衣会对关节角度计算造成误差因为MediaPipe是通过视觉特征推断骨架的衣服遮住了肢体轮廓就会导致估计漂移。这个在测试时一定要穿日常服装多跑几遍把阈值调到合理的范围。4. 系统集成双模态融合与门禁控制逻辑4.1 双模态融合策略两条识别链路都写完以后最核心的问题是怎么把两个人的“人脸相似度”和“步态相似度”综合成一个最终判断。这里我试过两种策略各有优劣。第一种是分数级融合把两个相似度做加权平均。人脸识别结果可靠性高的时候给0.7的权重步态给0.3人脸置信度低的时候反过来。这个方案理论上最优但实际调权重很麻烦容易出现过拟合。第二种是决策级融合也是我最终采用的策略先做人脸识别如果人脸相似度大于0.42这个阈值直接信任人脸结果如果人脸检测不到或者相似度介于0.42和0.6之间马上切到步态识别以步态结果为准两项都不达标就拒绝开门。相当于做人脸为主、步态兜底的双保险。4.2 SQLite数据库设计与人员管理系统需要一个轻量级的数据库来管理注册用户。我用的SQLitePython自带sqlite3模块零配置一个文件搞定对毕设来说完全够用。数据库包含三张核心表CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, student_id TEXT UNIQUE, register_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE face_features ( user_id INTEGER NOT NULL, face_encoding BLOB NOT NULL, camera_index INTEGER DEFAULT 0, FOREIGN KEY(user_id) REFERENCES users(id) ); CREATE TABLE gate_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, access_result TEXT, confidence REAL, access_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(user_id) REFERENCES users(id) );人脸特征向量以128维float数组的形式序列化为BLOB存进去。这里有个小细节特征向量存的是numpy数组的tobytes()结果读出来需要用np.frombuffer恢复别直接当字符串处理否则精度会出问题。步态特征我单独存成json文件放在data/gait_features/目录下因为步态特征是一个时间序列放到SQLite里反而查询不方便。注册的时候把正视角和侧视角各存一个特征序列文件命名规则直接关联用户ID。4.3 PyQt5界面与门禁控制界面我用PyQt5实现就三个核心区域视频画面实时预览区、状态信息显示区、操作按钮区。视频预览用QLabel定时刷新QImage识别的结果在状态区显示注册姓名、相似度和最终判定。门禁控制这块分两种模式。如果你的毕设是纯软件演示那就用模拟输出——识别成功的时候在界面上弹出绿灯和“允许通行”提示同时往数据库写一条通行记录这个效果演示足够了。如果你想接真实硬件那就在树莓派或者Jetson Nano上接一个继电器模块通过串口发送指令来控制电磁锁的开闭我用的是树莓派GPIO加5V继电器Python的RPi.GPIO库几行代码就能搞定import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) GPIO.setup(18, GPIO.OUT) def open_door(duration3): GPIO.output(18, GPIO.HIGH) # 继电器通电电磁锁打开 time.sleep(duration) GPIO.output(18, GPIO.LOW) # 断电门锁复位4.4 核心代码结构示例main.py是整个系统的主入口负责初始化数据库、加载特征库、启动摄像头和界面。关键的部分是识别逻辑的调度我用一个简单的状态机来管理class AccessController: def __init__(self): self.face_engine FaceRecognizer() self.gait_engine GaitRecognizer() self.face_score 0.0 self.gait_score 0.0 def process_frame(self, frame): # 优先人脸识别链路 self.face_score self.face_engine.recognize(frame) if self.face_score 0.42: if self.face_score 0.6: return self.face_engine.get_identity() else: # 置信度不足触发步态识别验证 self.gait_score self.gait_engine.verify(frame) if self.gait_score 0.65: return self.face_engine.get_identity() return None else: # 人脸识别完全失败尝试步态识别 self.gait_score self.gait_engine.verify(frame) if self.gait_score 0.65: return self.gait_engine.get_identity() return None5. 毕设实战排错与答辩避坑5.1 识别精度上不去这样排查我做这个项目的时候吃过不少亏总结下来最影响精度的几个原因数据集太单一、训练数据没有对齐、阈值设置不科学、特征预处理缺失。如果你发现人脸识别总是不准先检查注册照片质量是不是合格然后检查实时视频流是不是因为帧率低导致画面模糊。步态识别不准的话先别急着改算法把运行日志打开看看MediaPipe的骨架点检测置信度是不是稳定在0.8以上如果频繁掉点很可能是因为背景杂乱或者穿着宽松。阈值千万别拍脑袋定。正确做法是把所有测试样本的相似度分布统计出来画成直方图同一人的相似度应该集中在一个高分区不同人的相似度应该集中在低分区阈值选在两个分布的最低谷处这叫等错误率最优阈值。5.2 性能瓶颈与实时性优化人脸加步态两条识别链路同时跑对CPU的消耗是很大的。我的实测数据是i5-8250U的笔记本上face_recognition的单帧推理耗时约80msMediaPipe Pose单帧约30ms叠加起来已经有点卡了。性能优化的思路有几个方向。第一把步态识别做成“按需触发”也就是人脸识别置信度不够时才启动步态链路平时摄像头只跑人脸检测。第二降低处理分辨率把视频帧缩放到320x240再送进模型速度能提升一半以上。第三如果条件允许把模型放到GPU上face_recognition和MediaPipe都支持CUDA加速。5.3 系统说明文档与答辩演示的要点最后聊一下项目交付最重要的文档和演示。说明文档里我建议必须有需求分析、系统架构图、模块设计、关键算法原理、数据库设计、系统测试报告、项目总结和展望。测试报告这块特别容易被忽视但答辩老师一定会翻里面要有精确到型号的测试环境说明要有精度指标识别准确率、误识率、拒识率、性能指标帧率、响应时间还要有测试场景截图。答辩演示我有一个血泪教训一定要准备一个“视频演示”和一个“实时演示”两个方案。实时演示受现场光线、摄像头角度影响很大说不准就翻车。我的应对是录了一段完美的演示视频作为保底方案实时演示如果状态不好立马切视频演示不耽误讲原理和算法。最后再分享一个小技巧在说明文档里加一章限时控制和异常处理比如“连续识别失败3次触发报警”“识别超时自动退出当前流程”。不要小看这些细节它们正是体现你工程素养的地方也是评委最容易提问的点。我个人做下来的整体体会是这个毕设题目的上限很高拓展性也很强。做完之后如果再想想还可以往活体检测、多视角融合、嵌入式部署这些方向继续深入。但作为毕设来说重点其实是把“完整链路跑通”这件事做扎实。先把本地上的人脸和步态识别做稳定了把文档写得清晰漂亮你就已经超过大多数同学了。本文还有配套的精品资源点击获取
返回列表