1. 项目概述:基于机器视觉的驾驶疲劳检测系统
在长途驾驶或夜间行车场景中,驾驶员疲劳是引发交通事故的主要因素之一。传统基于生理信号的检测方法(如脑电图、肌电图)需要接触式传感器,在实际应用中存在明显局限。本项目采用非接触式的机器视觉方案,通过实时分析驾驶员面部特征实现疲劳状态检测。
系统核心功能模块包括:
- 人脸检测与特征点定位(Dlib库)
- 眼部状态分析(EAR算法)
- 嘴部状态分析(MAR算法)
- 头部姿态估计(HPE算法)
- 图形用户界面(PyQt5)
技术亮点在于多模态融合检测策略:当系统同时检测到闭眼时间过长(PERCLOS值超标)、频繁打哈欠(MAR值异常)以及头部持续低头(Pitch角超标)时,将触发三级预警机制。实测表明,该系统在1080P视频流中的处理速度达到24FPS,疲劳识别准确率达89.7%。
关键指标说明:PERCLOS(Percentage of Eyelid Closure Over the Pupil)是国际公认的疲劳度量标准,指单位时间内眼睛闭合时间占比。本系统设定阈值为12%,即3秒内闭眼时间超过0.36秒即触发初级预警。
2. 核心技术实现细节
2.1 Dlib人脸特征点检测
2.1.1 模型选型对比
我们测试了三种主流方案:
- OpenCV Haar级联检测器:速度最快(35FPS)但精度最低(68%)
- MTCNN:多任务卷积网络,精度较高(92%)但速度较慢(15FPS)
- Dlib HOG+SVM:平衡选择(24FPS/88%),且支持68点精确定位
最终选用dlib.shape_predictor加载预训练的68点模型(shape_predictor_68_face_landmarks.dat),该模型在300-W数据集上训练,关键点定位误差小于0.05。
2.1.2 关键点索引映射
python复制# 眼部特征点索引(左眼/右眼)
LEFT_EYE_POINTS = [36, 37, 38, 39, 40, 41]
RIGHT_EYE_POINTS = [42, 43, 44, 45, 46, 47]
# 嘴部特征点索引
MOUTH_POINTS = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59]
2.2 疲劳检测算法实现
2.2.1 眼部状态分析(EAR算法)
眼睛纵横比(Eye Aspect Ratio)计算公式:
code复制EAR = (||p2-p6|| + ||p3-p5||) / (2 * ||p1-p4||)
其中p1~p6对应眼部特征点位置(如图):

Python实现代码:
python复制def eye_aspect_ratio(eye):
A = dist.euclidean(eye[1], eye[5]) # p2-p6
B = dist.euclidean(eye[2], eye[4]) # p3-p5
C = dist.euclidean(eye[0], eye[3]) # p1-p4
return (A + B) / (2.0 * C)
实测数据:正常人EAR值在0.25-0.35之间波动,闭眼时EAR骤降至0.05以下。系统设定阈值为0.2,当连续3帧EAR<0.2判定为闭眼。
2.2.2 嘴部状态分析(MAR算法)
嘴部纵横比(Mouth Aspect Ratio)计算:
code复制MAR = (||p51-p59|| + ||p53-p57||) / (2 * ||p49-p55||)

优化策略:引入动态基线校准,每隔5分钟重新计算静息状态MAR值,消除个体差异影响。
2.2.3 头部姿态估计(HPE算法)
通过solvePnP求解3D-2D映射关系:
python复制# 3D模型参考点(单位:mm)
model_points = np.array([
(0.0, 0.0, 0.0), # 鼻尖
(0.0, -330.0, -65.0), # 下巴
(-225.0, 170.0, -135.0), # 左眼左角
# ...其他关键点
])
# 计算旋转向量和平移向量
_, rotation_vec, translation_vec = cv2.solvePnP(
model_points,
image_points,
camera_matrix,
dist_coeffs
)
# 转换为欧拉角
rotation_mat, _ = cv2.Rodrigues(rotation_vec)
pose_mat = cv2.hconcat((rotation_mat, translation_vec))
_, _, _, _, _, _, euler_angles = cv2.decomposeProjectionMatrix(pose_mat)
3. 系统优化与工程实践
3.1 性能提升方案
3.1.1 多线程处理框架
python复制class VideoStreamThread(QThread):
frame_signal = pyqtSignal(np.ndarray)
def __init__(self, src=0):
super().__init__()
self.stream = cv2.VideoCapture(src)
def run(self):
while True:
ret, frame = self.stream.read()
if ret:
self.frame_signal.emit(frame)
3.1.2 动态分辨率调整
根据CPU负载自动切换处理分辨率:
- 低负载:1080P全分辨率检测
- 中负载:720P检测+局部ROI精修
- 高负载:480P检测+关键帧分析
3.2 误判消除策略
- 眨眼误判过滤:设置最小闭眼持续时间(>100ms)
- 光照补偿:采用CLAHE算法增强眼部区域对比度
- 眼镜干扰处理:通过虹膜检测辅助判断
4. PyQt5界面开发要点
4.1 自定义无边框窗口
python复制class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowFlag(Qt.FramelessWindowHint)
# 实现窗口拖动
self._start_pos = None
self._end_pos = None
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self._start_pos = event.pos()
def mouseMoveEvent(self, event):
if self._start_pos:
self._end_pos = event.pos() - self._start_pos
self.move(self.pos() + self._end_pos)
4.2 样式表优化技巧
使用QSS实现现代化界面:
css复制/* 按钮悬停效果 */
QPushButton {
background-color: rgb(60, 60, 60);
border-radius: 5px;
padding: 8px;
color: white;
}
QPushButton:hover {
background-color: rgb(80, 80, 80);
}
5. 部署与测试结果
5.1 硬件兼容性测试
| 设备类型 | CPU占用率 | 内存占用 | 处理延迟 |
|---|---|---|---|
| Intel i7-11800H | 35% | 680MB | 42ms |
| Raspberry Pi 4B | 92% | 420MB | 210ms |
| Jetson Xavier NX | 58% | 520MB | 85ms |
5.2 典型场景识别率
| 场景描述 | 检测准确率 | 误报率 |
|---|---|---|
| 白天正常驾驶 | 91.2% | 3.5% |
| 夜间驾驶(有补光) | 85.7% | 6.1% |
| 佩戴太阳镜 | 78.3% | 8.9% |
| 侧脸(>30度偏转) | 65.4% | 12.3% |
6. 项目扩展方向
- 多模态数据融合:结合方向盘握力传感器数据提升准确率
- 边缘计算部署:使用TensorRT加速Dlib模型推理
- 云端监控平台:通过4G模块上传疲劳事件数据
- 自适应阈值调整:基于驾驶员历史数据动态优化参数
实际开发中发现三个关键经验:
- EAR阈值需要针对不同人种进行微调(亚洲人平均EAR比欧美人低0.03-0.05)
- 在颠簸路段需要结合车辆陀螺仪数据补偿头部运动干扰
- 系统预热阶段(前2分钟)应降低检测灵敏度以避免误报
