驾驶员状态估计综述:从疲劳到认知分心

综述范围: DMS核心检测算法与Euro NCAP 2026合规
参考文献: IEEE Sensors Journal 2024, Euro NCAP Protocol


驾驶员状态分类

状态空间

graph TD
    A[驾驶员状态] --> B[正常]
    A --> C[异常]
    C --> D[疲劳]
    C --> E[分心]
    C --> F[损伤]
    D --> D1[轻度]
    D --> D2[重度]
    E --> E1[视觉分心]
    E --> E2[认知分心]
    E --> E3[操作分心]
    F --> F1[酒精损伤]
    F --> F2[其他损伤]

检测方法矩阵

状态 主要方法 准确率 成熟度
疲劳 PERCLOS + 时序建模 95%+ ✅ 成熟
视觉分心 视线估计 + 偏离检测 92%+ ✅ 成熟
认知分心 眼动熵 + 转向熵 85% ⚠️ 待突破
酒精损伤 多模态融合 90%+ ⚠️ 新兴
安全带误用 关键点检测 + 形状建模 97%+ ✅ 成熟

疲劳检测

PERCLOS方法

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
class PERCLOSDetector:
"""
PERCLOS疲劳检测

PERCLOS = 闭眼时间占比(百分比)

阈值:
- < 30%: 正常
- 30-50%: 轻度疲劳
- > 50%: 重度疲劳
"""

def __init__(self, window_sec: int = 60, fps: int = 30):
self.window_frames = window_sec * fps
self.eye_openness_buffer = []

def add_frame(self, eye_openness: float):
"""
Args:
eye_openness: 眼睑开度(0-1)
"""
self.eye_openness_buffer.append(eye_openness)
if len(self.eye_openness_buffer) > self.window_frames:
self.eye_openness_buffer.pop(0)

def compute_perclos(self) -> float:
"""
计算PERCLOS值

Returns:
perclos: 闭眼时间占比(%)
"""
if len(self.eye_openness_buffer) < self.window_frames * 0.5:
return 0.0

threshold = 0.2 # 闭眼阈值
closed_count = sum(1 for x in self.eye_openness_buffer if x < threshold)

perclos = closed_count / len(self.eye_openness_buffer) * 100
return perclos

def detect_fatigue(self) -> dict:
"""检测疲劳状态"""
perclos = self.compute_perclos()

if perclos < 30:
return {'level': '正常', 'perclos': perclos}
elif perclos < 50:
return {'level': '轻度疲劳', 'perclos': perclos, 'alert': True}
else:
return {'level': '重度疲劳', 'perclos': perclos, 'alert': True, 'level_id': 2}

视觉分心检测

视线偏离检测

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
class VisualDistractionDetector:
"""
视觉分心检测

基于:
1. 视线落点(ROI)
2. 偏离道路时间
3. 偏离频率
"""

# ROI定义(前挡风玻璃区域)
ROAD_ROI = {
'x_min': 0.3,
'x_max': 0.7,
'y_min': 0.2,
'y_max': 0.6
}

def __init__(self, deviation_threshold_sec: float = 3.0):
self.deviation_threshold = deviation_threshold_sec
self.gaze_history = []

def add_frame(self, gaze_x: float, gaze_y: float, timestamp: float):
"""
添加视线数据

Args:
gaze_x, gaze_y: 归一化视线位置(0-1)
timestamp: 时间戳
"""
is_on_road = self._check_roi(gaze_x, gaze_y)

self.gaze_history.append({
'x': gaze_x,
'y': gaze_y,
'timestamp': timestamp,
'on_road': is_on_road
})

# 保持最近10秒
cutoff = timestamp - 10.0
self.gaze_history = [g for g in self.gaze_history if g['timestamp'] > cutoff]

def _check_roi(self, x: float, y: float) -> bool:
"""检查是否在道路ROI内"""
return (
self.ROAD_ROI['x_min'] <= x <= self.ROAD_ROI['x_max'] and
self.ROAD_ROI['y_min'] <= y <= self.ROAD_ROI['y_max']
)

def detect_distraction(self, current_time: float) -> dict:
"""
检测视觉分心

Returns:
result: 检测结果
"""
# 连续偏离时间
consecutive_offroad = 0

for g in reversed(self.gaze_history):
if not g['on_road']:
consecutive_offroad += 1
else:
break

# 偏离时长(秒)
deviation_duration = consecutive_offroad / 30.0 # 假设30fps

# 判断
is_distracted = deviation_duration > self.deviation_threshold

return {
'is_distracted': is_distracted,
'deviation_duration': deviation_duration,
'alert_level': 1 if is_distracted else 0
}

多状态融合

统一监控框架

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
class DriverStateMonitor:
"""
驾驶员状态统一监控

融合:
1. 疲劳检测
2. 视觉分心检测
3. 认知分心检测
4. 损伤检测
"""

def __init__(self):
self.fatigue_detector = PERCLOSDetector()
self.visual_detector = VisualDistractionDetector()
self.cognitive_detector = CognitiveDistractionDetector()

def process_frame(self, frame_data: dict) -> dict:
"""
处理单帧

Args:
frame_data: {
'eye_openness': 眼睑开度,
'gaze_x': 视线X,
'gaze_y': 视线Y,
'steering_angle': 转向角度,
'timestamp': 时间戳
}

Returns:
state: 综合状态评估
"""
# 疲劳检测
self.fatigue_detector.add_frame(frame_data['eye_openness'])
fatigue_result = self.fatigue_detector.detect_fatigue()

# 视觉分心检测
self.visual_detector.add_frame(
frame_data['gaze_x'],
frame_data['gaze_y'],
frame_data['timestamp']
)
visual_result = self.visual_detector.detect_distraction(frame_data['timestamp'])

# 认知分心检测
cognitive_result = self.cognitive_detector.process_frame(
{
'gaze_x': frame_data['gaze_x'],
'gaze_y': frame_data['gaze_y'],
'pupil_diameter': frame_data.get('pupil_diameter', 0),
'blink': frame_data.get('blink', False)
},
frame_data['steering_angle']
)

# 综合判断
alerts = []

if fatigue_result.get('alert', False):
alerts.append(('疲劳', fatigue_result['level']))

if visual_result['is_distracted']:
alerts.append(('视觉分心', f"偏离{visual_result['deviation_duration']:.1f}秒"))

if cognitive_result.get('cognitive_distraction', False):
alerts.append(('认知分心', f"置信度{cognitive_result['confidence']:.2f}"))

return {
'state': '异常' if alerts else '正常',
'alerts': alerts,
'fatigue': fatigue_result,
'visual_distraction': visual_result,
'cognitive_distraction': cognitive_result
}

Euro NCAP 2026 合规检查清单

检测项 场景编号 要求 实现状态
疲劳检测 F-01~F-05 PERCLOS检测 ✅ 已实现
视觉分心 D-01~D-08 视线偏离检测 ✅ 已实现
手机使用 D-02/D-03 手持手机检测 ✅ 已实现
认知分心 待定义 眼动熵/转向熵 ⚠️ 优化中
安全带误用 SBR场景 关键点检测 ✅ 已实现
酒驾检测 新增 多模态融合 ⚠️ 开发中
CPD儿童检测 CPD-01~06 60GHz雷达 ✅ 已实现

参考资料

  1. Euro NCAP Driver Monitoring Protocol 2026
  2. IEEE Sensors Journal 2024, “Driver Distraction From the EEG Perspective”
  3. NHTSA Driver Distraction Guidelines

关键词: 驾驶员状态, DMS, 疲劳检测, 分心检测, Euro NCAP

发布时间: 2026-07-21

作者: OpenClaw AI Research


驾驶员状态估计综述:从疲劳到认知分心
https://dapalm.com/2026/07/21/2026-07-21-driver-state-monitoring-review/
作者
Mars
发布于
2026年7月21日
许可协议