铁路驾驶员视觉疲劳检测:YOLOv8+注意力机制轻量CNN——秘鲁利马地铁实战部署

论文信息

项目 内容
标题 A vision-based drowsiness detection system for railway operators using lightweight convolutional neural networks
期刊 Frontiers in Future Transportation, Vol. 6
发表 2025年11月11日
链接 https://doi.org/10.3389/ffutr.2025.1677442
机构 UNTELS(秘鲁利马国立大学)
场景 Linea Uno利马地铁驾驶室
模型 YOLOv8 + 注意力机制
参数量 ~2.7M
准确率 96.8%

核心创新

  1. 铁路专属数据集:6,991帧真实地铁驾驶室视频,非汽车数据迁移
  2. YOLOv8+注意力:在YOLOv8基础上增加注意力机制聚焦关键面部区域
  3. 实时轻量:2.7M参数,满足实时推理需求
  4. 多光照验证:早/午/夜三种光照条件测试

问题定义

铁路vs汽车DMS差异

维度 汽车DMS 铁路DMS(本论文)
驾驶室环境 变化大 相对稳定
振动 中等 高(机车振动)
光照 日间/夜间 驾驶室人工照明
距离 50-70cm 60-65cm
帧率 25-60fps 30fps
分辨率 2MP+ 478×850像素
停靠 随时 固定站台

利马地铁特殊挑战

挑战 描述 影响
强阳光眩光 朝阳/夕阳直射驾驶室 检测准确率下降
隧道频繁 地铁线路大量隧道段 光照突变
长班次 6-12小时连续驾驶 疲劳累积
多线路 不同线路光照条件不同 泛化要求

方法详解

数据采集与处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import cv2
import numpy as np
from pathlib import Path

class RailwayDrowsinessDataset:
"""
铁路驾驶员疲劳数据集构建

论文方法:
1. 真实地铁驾驶室视频采集
2. 1/6采样降低冗余
3. MediaPipe面部特征点检测
4. 数据增强扩充多样性
"""

def __init__(self, video_path: str, output_dir: str = "dataset/"):
self.video_path = video_path
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)

# 论文参数
self.fps = 30
self.face_landmarks_idx = {
'left_eye': [33, 160, 158, 133], # 左眼4点
'right_eye': [362, 385, 387, 263], # 右眼4点
'mouth': [13, 14, 78, 308], # 嘴部4点
}
self.eye_closure_threshold = 18 # EAR<18为闭眼
self.yawn_threshold = 35 # MAR>35为哈欠
self.min_closure_ms = 833 # 闭眼>833ms为疲劳

def process_video(self):
"""
视频处理管道

论文流程:视频→帧提取→1/6采样→特征点→标注→增强
"""
cap = cv2.VideoCapture(self.video_path)

total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print(f"总帧数: {total_frames}")

# 1/6采样(论文方法)
sample_interval = 6
sampled_frames = []
frame_idx = 0

while cap.isOpened():
ret, frame = cap.read()
if not ret:
break

if frame_idx % sample_interval == 0:
sampled_frames.append(frame)
frame_idx += 1

cap.release()
print(f"采样后帧数: {len(sampled_frames)}")

# 面部特征点检测和标注
labeled_data = []
for i, frame in enumerate(sampled_frames):
landmarks = self._detect_landmarks(frame)
if landmarks is not None:
ear = self._calc_ear(landmarks)
mar = self._calc_mar(landmarks)

# 论文标注规则
if ear < self.eye_closure_threshold or mar > self.yawn_threshold:
label = 'Drowsy'
else:
label = 'Awake'

labeled_data.append({
'frame': frame,
'landmarks': landmarks,
'ear': ear,
'mar': mar,
'label': label,
})

return labeled_data

def _detect_landmarks(self, frame):
"""MediaPipe面部特征点检测"""
# 简化实现
h, w = frame.shape[:2]
# 返回模拟特征点
return np.random.rand(468, 2) * [w, h]

def _calc_ear(self, landmarks):
"""计算眼睑开度比(Eye Aspect Ratio)"""
le = self.face_landmarks_idx['left_eye']
re = self.face_landmarks_idx['right_eye']

left_ear = self._aspect_ratio(landmarks[le])
right_ear = self._aspect_ratio(landmarks[re])

return (left_ear + right_ear) / 2 * 100 # 放大100倍便于阈值

def _calc_mar(self, landmarks):
"""计算嘴部开度比(Mouth Aspect Ratio)"""
mouth = self.face_landmarks_idx['mouth']
return self._aspect_ratio(landmarks[mouth]) * 100

def _aspect_ratio(self, points):
"""计算宽高比"""
h = np.linalg.norm(points[0] - points[3])
w = (np.linalg.norm(points[1] - points[2]) +
np.linalg.norm(points[0] - points[1])) / 2
return h / (w + 1e-8)


class DataAugmentation:
"""
论文数据增强策略

使用Roboflow进行增强:
- 旋转: ±15°
- 亮度: ±20%
- 位移: 轻微
目标:模拟真实环境变化
"""

def __init__(self):
self.rotation_range = (-15, 15)
self.brightness_range = (-0.2, 0.2)

def augment(self, image: np.ndarray) -> list:
"""生成增强变体"""
augmented = [image] # 原图

# 旋转
for angle in [-15, 0, 15]:
if angle == 0:
continue
h, w = image.shape[:2]
M = cv2.getRotationMatrix2D((w/2, h/2), angle, 1)
rotated = cv2.warpAffine(image, M, (w, h))
augmented.append(rotated)

# 亮度
for b in [-0.2, 0.0, 0.2]:
if b == 0:
continue
bright = np.clip(
image * (1 + b), 0, 255
).astype(np.uint8)
augmented.append(bright)

return augmented


# 测试
if __name__ == "__main__":
# 数据集统计
print("=== 铁路疲劳数据集统计 ===")
print(f"原始帧数: 17,476")
print(f"采样后: 2,913 (1/6)")
print(f"增强后: 6,991")
print(f"训练集: 87% (6,082)")
print(f"验证集: 6.5% (454)")
print(f"测试集: 6.5% (454)")
print(f"\n闭眼阈值: EAR < 18")
print(f"哈欠阈值: MAR > 35")
print(f"疲劳判定: 闭眼 > 833ms")

YOLOv8+注意力架构

flowchart TD
    A[驾驶室视频帧] --> B[YOLOv8骨干]
    B --> C[注意力模块]
    C --> D[眼/嘴ROI检测]
    D --> E[EAR计算]
    D --> F[MAR计算]
    E --> G{EAR < 18?}
    F --> H{MAR > 35?}
    G -->|是| I[闭眼计时]
    H -->|是| J[哈欠计数]
    I --> K{>833ms?}
    K -->|是| L[疲劳警告]
    J --> L

实验结果

整体性能

指标 数值
准确率 96.8%
精确率 97.28%
召回率 97.46%
F1-Score 97.37%
参数量 2.7M
输入分辨率 640×640
帧率 30fps

时段性能对比

时段 光照条件 准确率 主要挑战
早间(6-10) 朝阳直射 94.2% 阳光眩光
午间(10-14) 均匀照明 98.1% 最佳条件
下午(14-18) 侧光/逆光 96.3% 阴影
夜间(18-24) 人工照明 97.5% 红外补光

与汽车DMS模型对比

模型 场景 准确率 参数量
YOLOv8+注意力(铁路) 地铁驾驶室 96.8% 2.7M
YOLOv5s(汽车) 车内 94.5% 7.2M
MobileNetV3+LSTM 车内 93.2% 1.5M
ResNet18+SVM 车内 91.7% 11.2M

IMS开发启示

1. 铁路→汽车技术迁移

铁路特性 汽车适配 技术复用
驾驶室稳定光照 车内光照变化 需增强光照鲁棒性
60-65cm摄像头距离 50-70cm 直接复用
EAR<18闭眼阈值 直接复用
MAR>35哈欠阈值 直接复用
833ms闭眼判定 可调 参数化

2. 与FATED框架的协同

组件 FATED #02 YOLOv8铁路 #本论文 协同
方法 连续体评估 实时检测 互补
输入 面部+骨骼 眼+嘴ROI 特征互补
决策 5阶段连续 二元疲劳/清醒 FATED更细致
部署 研究Phase I 实际部署 论文更落地

3. 多交通方式统一DMS架构

交通方式 摄像头 模型 延迟 部署
汽车 DMS摄像头 MobileNetV3 10ms QCS8255
铁路 驾驶室摄像头 YOLOv8+注意力 33ms 边缘PC
航空 驾驶舱摄像头 FATED框架 50ms 调度中心
船舶 桥楼摄像头 同铁路 33ms 边缘PC

总结

本论文是铁路驾驶员视觉疲劳检测的实际部署案例:

  1. 96.8%准确率+2.7M参数:轻量高效,适合边缘部署
  2. 真实地铁驾驶室验证:非模拟器,利马地铁Linea Uno
  3. 多光照条件测试:早/午/夜全覆盖,阳光眩光是最差条件
  4. EAR+MAR+闭眼时长三重判定:简单有效,可解释
  5. 与FATED连续体框架互补:实时检测+渐进评估=完整方案

https://dapalm.com/2026/09/22/2026-09-22-05-railway-yolov8-attention-drowsiness-lima-metro-ims/
作者
Mars
发布于
2026年9月22日
许可协议