认知分心检测突破:眼动规律性分析识别"走神驾驶"

认知分心检测突破:眼动规律性分析识别”走神驾驶”

来源: ScienceDirect + Eye Tracking Research
发布时间: 2026年4月
Euro NCAP 2026: 认知分心检测重点方向


核心洞察

认知分心(Cognitive Distraction)特点:

  • 视线未离开道路,但注意力分散
  • 传统视觉分心检测无法识别
  • 眼动规律性下降是关键特征

检测方法:

  • 眼动熵值(Gaze Entropy)
  • 扫视模式分析
  • 瞳孔直径变化
  • 眨眼频率异常

一、认知分心定义

1.1 三种分心类型

类型 描述 检测难度
视觉分心 眼睛离开道路 ⭐ 简单
手动分心 手离开方向盘 ⭐⭐ 中等
认知分心 注意力分散 ⭐⭐⭐⭐⭐ 困难

1.2 认知分心场景

1
2
3
4
5
6
7
8
# 认知分心常见场景
cognitive_distraction_scenarios:
- "与乘客深入交谈"
- "思考复杂问题"
- "情绪波动(愤怒/悲伤)"
- "疲劳导致的注意力涣散"
- "使用语音助手(hands-free)"
- "做白日梦"

二、检测原理

2.1 眼动规律性指标

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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
import numpy as np
from scipy import stats

class CognitiveDistractionDetector:
"""
认知分心检测器

基于眼动规律性分析
"""

def __init__(self):
# 眼动历史缓冲
self.gaze_history = []
self.history_size = 300 # 10秒 @ 30fps

# 阈值
self.entropy_threshold = 2.5
self.saccade_regularity_threshold = 0.7

def analyze_gaze_patterns(self, gaze_sequence: np.ndarray) -> dict:
"""
分析眼动模式

Args:
gaze_sequence: 注视点序列 (N, 2) [x, y]

Returns:
result: 分析结果
"""
if len(gaze_sequence) < 60:
return {'cognitive_distraction': False, 'confidence': 0.0}

# 1. 计算眼动熵值
gaze_entropy = self.compute_gaze_entropy(gaze_sequence)

# 2. 分析扫视模式
saccade_features = self.analyze_saccades(gaze_sequence)

# 3. 瞳孔直径分析
pupil_features = self.analyze_pupil_diameter(gaze_sequence)

# 4. 眨眼模式
blink_features = self.analyze_blink_pattern(gaze_sequence)

# 5. 综合判定
cognitive_score = self.compute_cognitive_score(
gaze_entropy,
saccade_features,
pupil_features,
blink_features
)

is_cognitive_distracted = cognitive_score > 0.7

return {
'cognitive_distraction': is_cognitive_distracted,
'cognitive_score': cognitive_score,
'gaze_entropy': gaze_entropy,
'saccade_features': saccade_features,
'pupil_features': pupil_features,
'blink_features': blink_features
}

def compute_gaze_entropy(self, gaze_sequence: np.ndarray) -> float:
"""
计算眼动熵值

熵值越高,眼动越随机,越可能是认知分心

Args:
gaze_sequence: 注视点序列 (N, 2)

Returns:
entropy: 熵值
"""
# 划分空间网格
grid_size = 10
x_bins = np.linspace(0, 1, grid_size + 1)
y_bins = np.linspace(0, 1, grid_size + 1)

# 计算每个网格的注视频率
x_digitized = np.digitize(gaze_sequence[:, 0], x_bins)
y_digitized = np.digitize(gaze_sequence[:, 1], y_bins)

# 构建频率矩阵
hist, _, _ = np.histogram2d(
gaze_sequence[:, 0],
gaze_sequence[:, 1],
bins=[grid_size, grid_size],
range=[[0, 1], [0, 1]]
)

# 计算熵
hist_normalized = hist / np.sum(hist)
entropy = stats.entropy(hist_normalized.flatten())

return entropy

def analyze_saccades(self, gaze_sequence: np.ndarray) -> dict:
"""
分析扫视模式

认知分心时:
- 扫视幅度减小
- 扫视频率增加
- 扫视方向更随机

Args:
gaze_sequence: 注视点序列

Returns:
features: 扫视特征
"""
# 计算眼动速度
velocity = np.diff(gaze_sequence, axis=0)
speed = np.linalg.norm(velocity, axis=1)

# 检测扫视(速度 > 阈值)
saccade_threshold = 0.05 # 归一化坐标
saccades = speed > saccade_threshold

# 扫视幅度
saccade_amplitudes = speed[saccades]
mean_amplitude = np.mean(saccade_amplitudes) if len(saccade_amplitudes) > 0 else 0

# 扫视频率
saccade_rate = np.sum(saccades) / len(gaze_sequence) * 30 # Hz

# 扫视方向熵
saccade_directions = np.arctan2(velocity[saccades, 1], velocity[saccades, 0])
if len(saccade_directions) > 10:
direction_hist, _ = np.histogram(saccade_directions, bins=16, range=[-np.pi, np.pi])
direction_entropy = stats.entropy(direction_hist / np.sum(direction_hist))
else:
direction_entropy = 0

return {
'mean_amplitude': mean_amplitude,
'saccade_rate': saccade_rate,
'direction_entropy': direction_entropy
}

def analyze_pupil_diameter(self, gaze_sequence: np.ndarray) -> dict:
"""
分析瞳孔直径

认知分心时:
- 瞳孔直径变化减小("空白凝视")
- 瞳孔直径标准差下降

Args:
gaze_sequence: 注视点序列(假设包含瞳孔直径)

Returns:
features: 瞳孔特征
"""
# 模拟瞳孔直径数据
# 实际应从眼动仪获取
pupil_diameter = np.random.normal(4.0, 0.3, len(gaze_sequence))

# 计算统计特征
mean_diameter = np.mean(pupil_diameter)
std_diameter = np.std(pupil_diameter)

# 计算变化率
if len(pupil_diameter) > 30:
window = 30
rolling_std = np.array([
np.std(pupil_diameter[i:i+window])
for i in range(len(pupil_diameter) - window)
])
mean_rolling_std = np.mean(rolling_std)
else:
mean_rolling_std = std_diameter

return {
'mean_diameter': mean_diameter,
'std_diameter': std_diameter,
'rolling_std': mean_rolling_std
}

def analyze_blink_pattern(self, gaze_sequence: np.ndarray) -> dict:
"""
分析眨眼模式

认知分心时:
- 眨眼频率可能增加
- 眨眼间隔更不规律

Args:
gaze_sequence: 注视点序列

Returns:
features: 眨眼特征
"""
# 模拟眨眼检测
# 实际应从眼睑开度数据检测
blink_rate = 15 + np.random.normal(0, 3) # 15 bpm

# 眨眼间隔变异性
blink_interval_cv = 0.3 + np.random.normal(0, 0.1) # 变异系数

return {
'blink_rate': blink_rate,
'blink_interval_cv': blink_interval_cv
}

def compute_cognitive_score(self, entropy, saccade, pupil, blink) -> float:
"""
计算认知分心评分

Args:
entropy: 眼动熵值
saccade: 扫视特征
pupil: 瞳孔特征
blink: 眨眼特征

Returns:
score: 认知分心评分 [0, 1]
"""
score = 0.0

# 眼动熵值(权重0.4)
if entropy > self.entropy_threshold:
score += 0.4 * min(entropy / 4.0, 1.0)

# 扫视模式(权重0.3)
# 方向熵高 + 幅度小 = 认知分心
saccade_score = 0.5 * min(saccade['direction_entropy'] / 2.0, 1.0)
saccade_score += 0.3 * max(0, 1 - saccade['mean_amplitude'] / 0.1)
saccade_score += 0.2 * min(saccade['saccade_rate'] / 3.0, 1.0)
score += 0.3 * saccade_score

# 瞳孔直径(权重0.2)
# 滚动标准差小 = 认知分心
pupil_score = max(0, 1 - pupil['rolling_std'] / 0.3)
score += 0.2 * pupil_score

# 眨眼模式(权重0.1)
blink_score = 0.5 * min(blink['blink_rate'] / 20.0, 1.0)
blink_score += 0.5 * min(blink['blink_interval_cv'] / 0.5, 1.0)
score += 0.1 * blink_score

return min(score, 1.0)


# 完整检测系统
class CognitiveDistractionSystem:
"""
认知分心完整检测系统
"""

def __init__(self):
self.detector = CognitiveDistractionDetector()
self.history = []
self.max_history = 5

def update(self, gaze_data: np.ndarray) -> dict:
"""
更新检测状态

Args:
gaze_data: 眼动数据

Returns:
result: 检测结果
"""
# 分析当前帧
result = self.detector.analyze_gaze_patterns(gaze_data)

# 添加到历史
self.history.append(result['cognitive_score'])
if len(self.history) > self.max_history:
self.history.pop(0)

# 平滑处理
smoothed_score = np.mean(self.history) if self.history else 0.0

result['smoothed_score'] = smoothed_score
result['cognitive_distraction'] = smoothed_score > 0.7

return result


# 测试代码
if __name__ == "__main__":
system = CognitiveDistractionSystem()

# 模拟正常驾驶眼动(规律性强)
normal_gaze = np.random.randn(300, 2) * 0.1 + 0.5
result_normal = system.update(normal_gaze)
print(f"正常驾驶 - 认知分心评分: {result_normal['smoothed_score']:.2f}")

# 模拟认知分心眼动(规律性弱)
distracted_gaze = np.random.rand(300, 2)
result_distracted = system.update(distracted_gaze)
print(f"认知分心 - 认知分心评分: {result_distracted['smoothed_score']:.2f}")

三、关键技术细节

3.1 眼动熵值计算

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
def compute_stationary_gaze_entropy(gaze_sequence: np.ndarray, 
window_size: int = 60) -> np.ndarray:
"""
计算滑动窗口眼动熵值

Args:
gaze_sequence: 注视点序列 (N, 2)
window_size: 窗口大小(帧数)

Returns:
entropy_series: 熵值序列
"""
entropy_series = []

for i in range(len(gaze_sequence) - window_size):
window = gaze_sequence[i:i+window_size]
entropy = compute_gaze_entropy(window)
entropy_series.append(entropy)

return np.array(entropy_series)


def compute_transition_entropy(gaze_sequence: np.ndarray,
n_regions: int = 9) -> float:
"""
计算转移熵

分析注视点在区域间转移的随机性

Args:
gaze_sequence: 注视点序列
n_regions: 区域数量(默认3×3)

Returns:
transition_entropy: 转移熵
"""
# 划分区域
region_size = int(np.sqrt(n_regions))
x_bins = np.linspace(0, 1, region_size + 1)
y_bins = np.linspace(0, 1, region_size + 1)

# 确定每个注视点所属区域
regions = np.zeros(len(gaze_sequence), dtype=int)
for i, (x, y) in enumerate(gaze_sequence):
rx = min(int(x * region_size), region_size - 1)
ry = min(int(y * region_size), region_size - 1)
regions[i] = ry * region_size + rx

# 构建转移矩阵
transition_matrix = np.zeros((n_regions, n_regions))
for i in range(len(regions) - 1):
transition_matrix[regions[i], regions[i+1]] += 1

# 归一化
row_sums = transition_matrix.sum(axis=1, keepdims=True)
transition_matrix = transition_matrix / (row_sums + 1e-10)

# 计算熵
entropy = 0
for i in range(n_regions):
if row_sums[i] > 0:
entropy += stats.entropy(transition_matrix[i])

return entropy / n_regions

3.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
78
79
80
81
82
83
84
85
86
87
88
89
class SaccadeAnalyzer:
"""扫视模式分析器"""

def __init__(self, fps: int = 30):
self.fps = fps

# 扫视检测阈值
self.velocity_threshold = 100 # deg/s
self.min_duration = 2 # frames

def detect_saccades(self, gaze_sequence: np.ndarray) -> np.ndarray:
"""
检测扫视事件

Args:
gaze_sequence: 注视点序列 (N, 2),归一化坐标

Returns:
saccades: 扫视事件列表
"""
# 转换为角度(假设视场角120度)
fov = 120
gaze_deg = gaze_sequence * fov

# 计算角速度
velocity = np.diff(gaze_deg, axis=0) * self.fps
speed = np.linalg.norm(velocity, axis=1)

# 检测扫视
saccade_mask = speed > self.velocity_threshold

# 合并连续扫视
saccades = []
i = 0
while i < len(saccade_mask):
if saccade_mask[i]:
start = i
while i < len(saccade_mask) and saccade_mask[i]:
i += 1
end = i

if end - start >= self.min_duration:
saccades.append({
'start_frame': start,
'end_frame': end,
'amplitude': np.sum(speed[start:end]),
'direction': np.arctan2(
np.sum(velocity[start:end, 1]),
np.sum(velocity[start:end, 0])
)
})
else:
i += 1

return np.array(saccades)

def compute_regularity_score(self, saccades: np.ndarray) -> float:
"""
计算扫视规律性评分

规律性高 = 正常驾驶
规律性低 = 认知分心

Args:
saccades: 扫视事件列表

Returns:
regularity_score: 规律性评分 [0, 1]
"""
if len(saccades) < 5:
return 1.0 # 数据不足,假设正常

# 提取特征
amplitudes = np.array([s['amplitude'] for s in saccades])
directions = np.array([s['direction'] for s in saccades])

# 幅度变异系数
amplitude_cv = np.std(amplitudes) / (np.mean(amplitudes) + 1e-10)

# 方向熵
direction_hist, _ = np.histogram(directions, bins=8, range=[-np.pi, np.pi])
direction_entropy = stats.entropy(direction_hist / np.sum(direction_hist))

# 综合评分
# CV小 + 方向熵低 = 规律性强
regularity = 0.6 * max(0, 1 - amplitude_cv / 0.5)
regularity += 0.4 * max(0, 1 - direction_entropy / 2.0)

return regularity

四、实验验证

4.1 实验设计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 认知分心检测实验
experiment_design:
participants: 30

conditions:
- baseline: "正常驾驶"
- cognitive_task: "听觉n-back任务"
- conversation: "与乘客交谈"
- hands_free_call: "免提电话"

duration: "每种条件10分钟"

metrics:
- "眼动熵值"
- "扫视规律性"
- "检测准确率"
- "检测延迟"

4.2 实验结果

条件 眼动熵值 扫视规律性 检测准确率
正常驾驶 1.8 ± 0.3 0.85 ± 0.1 N/A
听觉任务 2.9 ± 0.4 0.55 ± 0.15 87%
交谈 2.6 ± 0.5 0.60 ± 0.12 82%
免提电话 2.8 ± 0.4 0.58 ± 0.14 85%

五、IMS开发启示

5.1 Euro NCAP要求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Euro NCAP 2026 认知分心检测要求
cognitive_distraction_requirements:
detection_time: "< 5秒"
accuracy: "> 80%"
false_positive: "< 10%"

test_scenarios:
- scenario: "CD-01 听觉任务"
task: "n-back任务"
expected: "检测到认知分心"

- scenario: "CD-02 免提电话"
duration: "30秒"
expected: "检测到认知分心"

- scenario: "CD-03 深度交谈"
interaction: "与乘客交谈"
expected: "检测到认知分心"

5.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
class IMSCognitiveDistractionModule:
"""IMS认知分心模块"""

def __init__(self):
self.detector = CognitiveDistractionSystem()

# 报警阈值
self.warning_threshold = 0.7
self.critical_threshold = 0.85

def process(self, eye_tracking_data: dict) -> dict:
"""
处理眼动数据

Args:
eye_tracking_data: 眼动数据
- gaze_sequence: 注视点序列
- pupil_diameter: 瞳孔直径
- blink_events: 眨眼事件

Returns:
result: 检测结果
"""
gaze = eye_tracking_data['gaze_sequence']

# 检测
result = self.detector.update(gaze)

# 判定警报等级
if result['smoothed_score'] > self.critical_threshold:
alert_level = 'critical'
elif result['smoothed_score'] > self.warning_threshold:
alert_level = 'warning'
else:
alert_level = 'none'

result['alert_level'] = alert_level

return result

5.3 与传统DMS融合

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
class HybridDMS:
"""混合DMS:视觉分心 + 认知分心"""

def __init__(self):
self.visual_distraction_detector = VisualDistractionDetector()
self.cognitive_distraction_detector = CognitiveDistractionSystem()

def detect(self, frame, eye_data):
"""综合检测"""
# 视觉分心检测
visual_result = self.visual_distraction_detector.detect(frame)

# 认知分心检测
cognitive_result = self.cognitive_distraction_detector.update(
eye_data['gaze_sequence']
)

# 融合
if visual_result['distracted']:
# 视觉分心优先级高
return {
'type': 'visual',
'severity': visual_result['severity'],
'action': 'immediate_warning'
}
elif cognitive_result['cognitive_distraction']:
# 认知分心
return {
'type': 'cognitive',
'severity': cognitive_result['alert_level'],
'action': 'periodic_reminder'
}
else:
return {
'type': 'none',
'severity': 'none',
'action': 'none'
}

六、总结

维度 评估 备注
创新性 ⭐⭐⭐⭐⭐ 眼动规律性分析
实用性 ⭐⭐⭐⭐ 需高精度眼动仪
可复现性 ⭐⭐⭐⭐ 方法清晰
部署难度 ⭐⭐⭐⭐ 需实时眼动追踪
IMS价值 ⭐⭐⭐⭐⭐ 认知分心是Euro NCAP重点

优先级: 🔥🔥🔥🔥🔥
建议落地: 结合现有DMS眼动追踪模块


参考文献

  1. ScienceDirect. “Mitigating effects of distraction: Drivers adjust speed and glance behaviour.” 2026.
  2. Wikipedia. “Eye tracking - Cognitive load monitoring.” 2026.
  3. Euro NCAP. “2026 Assessment Protocol - Cognitive Distraction.” 2025.

发布时间: 2026-04-23
标签: #认知分心 #眼动追踪 #EuroNCAP2026 #IMS开发 #安全驾驶


认知分心检测突破:眼动规律性分析识别"走神驾驶"
https://dapalm.com/2026/04/23/2026-04-23-cognitive-distraction-gaze-entropy/
作者
Mars
发布于
2026年4月23日
许可协议