
简介面向高校计算机专业毕业设计人群这份Python源码实现了基于驾驶员面部特征的疲劳检测系统通过人脸识别分析眼部、嘴部等关键状态自动判断驾驶员是否需要休息也适用于交通监控、高速收费站等疲劳驾驶预警场景。整个压缩包共24个文件、大小约68.33MB核心为5个py脚本分别负责检测与判定逻辑配套10个xml配置文件和2个iml工程文件可帮助IDE快速识别项目结构docx、md、txt提供说明文档mp3用于疲劳语音提醒dat文件保存特征数据整体源码结构清晰便于按模块阅读。项目已有1357人学习下载说明其在毕业设计场景下具备较高的参考价值和使用基础。下载后可直接导入PyCharm等环境运行便于快速复现实验并可根据实际需求调整检测阈值、扩展接口或接入摄像头视频流方便进一步研究疲劳检测算法细节。对于需要完成人脸识别类毕业设计、学习疲劳检测完整流程的同学这份源码提供了简洁可用的基础框架和可直接演示的项目素材同时有助于锻炼工程实现与二次开发能力。 最近后台收到好几个同学私信都在问基于Python的驾驶员疲劳检测系统怎么做说搜了一圈源码要么跑不起来要么代码注释少得可怜根本没法交毕业设计。我自己前前后后帮人调过好几版这类系统从最早用OpenCV硬算眼睛长宽比到后来接Dlib做68点关键点检测踩过的坑确实不少。这篇就把这套系统的核心逻辑、完整实现流程、以及最容易出问题的细节一次性说清楚想拿来做课设或者毕业设计的同学可以直接照着思路复现。这套系统说白了就是让电脑通过摄像头实时判断一个人是不是在打瞌睡。核心链路是摄像头抓帧 - 人脸检测 - 定位面部关键点尤其眼睛周围- 计算眼睛开合程度 - 根据连续帧的闭眼频率和时长判定疲劳状态 - 触发报警。整条链路全部用Python实现配合OpenCV和Dlib两个库就能跑通这也是当前绝大多数毕设选题里最主流的方案。1. 方案选型为什么主流毕设都选Dlib而非深度学习1.1 不同实现路径的优劣对比疲劳检测的实现路线并不只有一条。我在给不同需求的同学做技术评估时一般会列出三条路线传统图像处理、经典机器学习、深度学习。三者各有各的适用场景。传统图像处理路线典型的做法是利用Haar特征做眼睛区域检测然后靠像素灰度分布判断眼睛闭合状态。优点是代码量小、运行极快缺点是鲁棒性非常差戴眼镜、光线变化、头部转动都会让准确率直接崩掉只适合做演示用。经典机器学习路线比如训练一个SVM或HOG分类器来区分睁眼闭眼比传统方法要强一些但你需要自己去准备标注数据集这个工作量对于毕设来说并不小。深度学习路线目前效果最好比如用YOLO检测人脸区域、用OpenFace或MediaPipe做面部关键点提取。但缺点是你要跑模型训练或者至少需要较重的推理框架对于很多连环境都装不利索的同学来说光配置CUDA和Torch就能折腾一星期。1.2 Dlib方案的核心优势折中下来Dlib的HOG 线性分类器做人脸检测配合预训练好的68点面部关键点模型是目前毕设场景下综合性价比最高的方案。首先Dlib官方提供了训练好的shape_predictor_68_face_landmarks.dat模型你不需要自己采样和标注下载直接用即可。其次Dlib的CPU推理速度很快普通笔记本上跑实时视频流完全可以做到每秒20帧以上。更重要的是代码难度低关键点提取只需要几行API调用把精力留在逻辑层这对于毕设项目来说极其重要。这套选型思路对应到最终的实现架构就是OpenCV负责图像采集和展示Dlib负责定位68个关键点numpy做坐标运算然后基于EAR算法计算眼睛纵横比加上阈值判定和报警触发整个系统就成型了。2. 环境搭建从Python到Dlib的完整安装指南2.1 基础环境配置要点开始写代码之前先把环境搞定。疲劳检测系统对Python版本要求不苛刻3.7到3.10都没问题我建议用3.8或3.9兼容性最好。如果电脑还没装Python直接去官网下载对应版本安装时记得勾选Add Python to PATH这一步不勾后面命令行输python会提示找不到命令。装完之后建议用虚拟环境管理依赖不要让全局环境越来越乱。在项目目录下打开终端执行python -m venv venv venv\Scripts\activate # Windows source venv/bin/activate # Linux/Mac2.2 核心依赖库安装激活虚拟环境后依次安装四个核心库pip install opencv-python pip install dlib pip install numpy pip install imutilsOpenCV是图像处理和摄像头操作的主力imutils是方便做图像缩放等操作的辅助库。numpy不用多说坐标计算全靠它。这里头最麻烦的是Dlib的安装。在Windows上pip直接装dlib经常会碰到编译错误因为Dlib需要CMake和C编译器。我的建议是优先尝试pip安装如果报错再考虑两种替代方案第一种去Visual Studio官网安装Desktop development with C工作负载装完重开终端再执行pip install dlib这种方案最彻底。第二种直接找别人编译好的whl版本文件下载到本地再pip install可以省去编译时间但要注意whl版本必须和你的Python版本、系统位数匹配。2.3 模型文件下载与项目目录规划Dlib的68点模型文件在网上可以直接搜到shape_predictor_68_face_landmarks.dat文件大约100MB左右需要单独下载。下载后放在项目的models目录下。一个清晰的目录结构对于毕设答辩很重要我习惯这样组织driver-fatigue-detection/ ├── main.py # 主程序入口 ├── config.py # 参数配置阈值、报警时间等 ├── models/ │ └── shape_predictor_68_face_landmarks.dat └── utils/ ├── __init__.py ├── eye_aspect_ratio.py # EAR计算函数 └── alarm.py # 报警模块这种结构的好处是把功能拆分清楚答辩时老师问每个文件是干什么的你能答得条理分明。3. EAR算法原理眼睛开合度的精确数学表达3.1 68个关键点与眼部特征点定位Dlib的68点面部关键点模型把脸部分成了若干个区域下颌轮廓17个点、眉毛5个点、鼻子9个点、眼睛12个点、嘴巴20个点另外还有面部轮廓的若干点。其中真正用于疲劳检测的是左右眼周围的12个点左眼索引是36到41右眼索引是42到47。每一只眼睛周围6个点这些点形成了一个近似菱形的轮廓。当人睁眼时这个菱形在垂直方向上的开口较大当人闭眼时上下眼睑的点会靠近甚至重合。EAR算法就是把这个几何特征转换为一个数值指标。3.2 EAR计算公式与标准阈值EAREye Aspect Ratio眼睛纵横比的计算公式如下def eye_aspect_ratio(eye): # 计算眼睛垂直方向上的两对关键点之间的欧氏距离 A dist.euclidean(eye[1], eye[5]) B dist.euclidean(eye[2], eye[4]) # 计算眼睛水平方向上的关键点之间的欧氏距离 C dist.euclidean(eye[0], eye[3]) # EAR (A B) / (2 * C) ear (A B) / (2.0 * C) return ear其中eye是一个包含6个坐标点的列表排列顺序是眼头到眼尾方向依次排列。分子中的A对应上下眼睑第一对点的距离B是第二对点的距离C是眼头到眼尾的水平距离。人在正常睁眼状态下EAR大约在0.25到0.35之间。当眼睛开始闭合时垂直距离迅速减小EAR值随之快速下降。闭眼状态下EAR会趋近于0。学术界和工程实践中常用的闭眼判定阈值是0.2也就是说EAR低于0.2时认为眼睛处于闭合状态。但这个值并不是绝对的每个人的眼睛大小和睁开幅度不一样实际部署时最好校准一次。我在调系统时发现阈值设置太敏感会导致戴眼镜的同学频繁误报太迟钝又检测不到轻微瞌睡。合理的做法是把阈值设置在0.18到0.25之间根据实际测试情况微调。另外可以做一个简单的自适应校准在系统启动前采集用户正常睁眼状态的EAR均值用这个均值的70%作为动态阈值。4. 实时检测系统完整实现代码逐段拆解4.1 初始化模型与打开摄像头主程序的第一步是加载Dlib的面部检测器和关键点预测器同时打开摄像头。这里有个细节要注意Dlib提供了两个检测器get_frontal_face_detector()检测人脸框shape_predictor加载模型预测关键点。import cv2 import dlib import numpy as np from scipy.spatial import distance as dist # 加载预训练模型 detector dlib.get_frontal_face_detector() predictor dlib.shape_predictor(models/shape_predictor_68_face_landmarks.dat) # 定义左右眼的关键点索引 LEFT_EYE_START, LEFT_EYE_END 36, 42 RIGHT_EYE_START, RIGHT_EYE_END 42, 48 # 打开摄像头 cap cv2.VideoCapture(0) if not cap.isOpened(): raise IOError(无法打开摄像头请检查设备索引或驱动)摄像头打不开是高频问题排查思路是先确认设备管理器里能看到摄像头然后试试把VideoCapture参数从0改成1因为有些笔记本的自带摄像头索引并不是0。4.2 核心循环实时抓帧与关键点提取系统主干是一个while循环持续从摄像头读取图像帧。为了提高速度每帧先做灰度转换再缩小尺寸到宽度500像素左右这样可以显著降低面部检测的计算量。while True: ret, frame cap.read() if not ret: break # 缩小帧以加速检测 frame imutils.resize(frame, width500) gray cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 检测人脸 faces detector(gray, 0) for face in faces: # 获取关键点 landmarks predictor(gray, face) # 转为numpy数组方便计算 landmarks_np np.array([[p.x, p.y] for p in landmarks.parts()]) # 提取左右眼的关键点坐标 left_eye landmarks_np[LEFT_EYE_START:LEFT_EYE_END] right_eye landmarks_np[RIGHT_EYE_START:RIGHT_EYE_END] # 计算EAR值 left_ear eye_aspect_ratio(left_eye) right_ear eye_aspect_ratio(right_eye) ear (left_ear right_ear) / 2.0 # 绘制关键点 for i in range(36, 48): cv2.circle(frame, (landmarks_np[i][0], landmarks_np[i][1]), 2, (0, 255, 0), -1)以上每次循环会输出一个当前帧的平均EAR值左右眼分别计算的用意在于消除单侧遮挡或角度带来的误差。4.3 疲劳判定逻辑连续帧闭眼统计单个画面帧EAR低于阈值还不足以说明疲劳因为正常人也经常眨眼单次眨眼持续约100到400毫秒对应到30帧每秒的摄像头就是3到12帧。所以判断疲劳必须基于连续时间窗口内的闭眼比例。我采用的策略是记录EAR低于阈值的帧数counter当counter连续超过一个设定值时判定为一次闭眼事件。然后维护一个闭眼帧率指标比如在最近60秒内如果闭眼帧数占总帧数的比例超过15%或者出现连续3秒以上眼睛闭合的情况就判断为疲劳状态。EYE_AR_THRESH 0.2 # EAR低于该值视为闭眼 EYE_AR_CONSEC_FRAMES 48 # 连续闭眼48帧触发疲劳报警约1.6秒 frame_counter 0 alarm_on False # 在检测循环内部 if ear EYE_AR_THRESH: frame_counter 1 if frame_counter EYE_AR_CONSEC_FRAMES: if not alarm_on: alarm_on True cv2.putText(frame, FATIGUE DETECTED!, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 255), 2) # 触发声音报警 alarm_trigger() else: frame_counter 0 alarm_on FalseEYE_AR_CONSEC_FRAMES48这个值的含义是假设摄像头是30帧每秒48帧就代表1.6秒的持续性闭眼。正常人正常眨眼不会持续这么久所以这个值能有效防止误报。这个阈值设定的逻辑需要写进论文或答辩说明里老师一定会问到。5. 功能扩展与创新点设计拉开毕设档次的加分项5.1 哈欠检测与头部姿态估计只做眼睛疲劳检测能拿个基础分想拿高分需要适当增加创新点。最容易加的两个功能是哈欠检测和头部姿态估计。哈欠检测的原理和眼睛检测类似Dlib的68点模型里嘴巴周围有20个点索引从48到67。计算嘴巴纵横比MARMouth Aspect Ratio当MAR超过阈值且持续一定帧数时判定为哈欠。多个连续哈欠可以进一步增强疲劳判断的置信度。头部姿态估计稍微复杂一些思路是利用人脸关键点二维坐标和标准三维人脸模型的对应关系通过solvePnP算法估计头部的旋转角度。当头部频繁低头或大角度倾斜时同样提示疲劳。OpenCV提供了cv2.solvePnP函数传入3D人脸基准点和对应的2D关键点即可求出旋转向量再转换成欧拉角。5.2 数据记录与可视化界面为了展现系统的完整性建议把检测结果持久化到本地每隔一分钟记录一次平均EAR值、闭眼次数、疲劳状态等数据使用CSV格式存储。答辩时可以直接展示这段时间的数据变化趋势说明系统确实在持续工作。如果想要界面更好看可以用PyQt5或者Tkinter做一个简单的桌面应用把视频画面嵌入窗口疲劳状态用红灯绿灯指示报警记录显示在右侧列表。这一步虽然不是核心功能但视觉呈现效果会直接影响答辩评分。5.3 参数配置模块的设计思路把阈值、帧率、报警声音路径等参数单独抽到config.py的好处是答辩演示时可以当着老师的面修改阈值现场演示系统参数调整对结果的影响这个动作比任何口头解释都有说服力。# config.py EYE_AR_THRESH 0.2 EYE_AR_CONSEC_FRAMES 48 MOUTH_AR_THRESH 0.6 MOUTH_CONSEC_FRAMES 30 ALARM_SOUND_PATH alarm.wav MODE all # eye/mouth/head/all6. 高频报错与实操心法血泪踩坑记录6.1 Dlib安装失败这个问题出现频率极高。Windows下pip install dlib最常见的报错是找不到CMake或者无法找到Visual Studio编译器。我的调试建议是先安装CMake并加入PATH再安装Visual Studio Build Tools勾选C桌面开发组件装完重启终端再试。还是不行的话就直接下载对应版本的whl安装包用pip install安装本地文件这条路径成功率最高。6.2 摄像头画面卡顿严重卡顿的原因多半不是算法慢而是每一帧的分辨率太高。默认的1280x720摄像头画面跑Dlib检测非常吃力。解决方案是先用cv2.CAP_PROP_FRAME_WIDTH和cv2.CAP_PROP_FRAME_HEIGHT把摄像头分辨率降到640x480或者在读帧之后resize到宽度400到500像素。实测可以把帧率从8帧提升到25帧以上。6.3 戴眼镜或强光下误报严重Dlib关键点检测在强反光、逆光和戴墨镜场景下效果会变差。提升鲁棒性的手段有几个一是把图像做直方图均衡化通过cv2.equalizeHist增强对比度二是把单帧眨眼滤除利用眨眼持续时间作为辅助判据三是条件允许的情况下用红外摄像头IR光源下关键点检测受可见光干扰很小。6.4 程序退出时摄像头资源释放很多同学的代码里没有处理释放资源的逻辑运行一段时间后摄像头被占用导致下次启动失败。主循环结束后需要执行cap.release()和cv2.destroyAllWindows()用键盘按q退出循环之前也要确保这两行被调用。7. 从毕设到实际工程的差距与改进方向真诚地讲这类基于传统图像特征的疲劳检测系统在受控环境下效果不错但距离真正的商业级落地还有明显差距。实际行车环境下光照剧烈变化、驾驶员频繁转头、视线偏离摄像头、墨镜遮挡等问题都会让Dlib方案的准确率下降。商用系统通常要结合车内红外摄像头、方向盘转向传感器、车道偏离预警等多模态数据才能达到足够的可靠性。如果你的毕业设计有余力可以往深度学习方向探索一下比如用PyTorch搭建一个小型卷积网络替代Dlib的关键点检测或者直接用MediaPipe的Face Mesh模型能做到468个面部关键点的实时检测精度和鲁棒性都比Dlib高一个量级。但作为毕设Dlib方案已经足够展示你对图像处理、特征工程和实时系统设计的理解。最后再分享一个写论文和做答辩PPT时的小技巧不要只放系统的最终效果截图最好准备一张从原始帧到灰度图、人脸框、关键点标定、EAR曲线变化、疲劳状态输出的完整流程图。这张图能一次性串起你论文里最核心的五六个章节老师顺着图问你的时候你答起来也会更有条理。做这类项目别指望一遍跑通耐心调试才是常态。本文还有配套的精品资源点击获取