认知分心检测新突破:眼动熵指数量化方法

认知分心检测新突破:眼动熵指数量化方法

Euro NCAP 2026认知分心要求

Euro NCAP 2026首次将”认知分心”(Cognitive Distraction)纳入DSM检测范畴,这是继疲劳和视觉分心后的第三大分心类型。

认知分心定义:
驾驶员视线保持在道路上,但注意力被内部思维活动占用,如:

  • 沉思、走神
  • 情绪波动
  • 复杂心算
  • 白日梦

检测难点:

挑战 描述 解决方案
无外部线索 没有明显的视线偏离 需要眼动微观特征
难以量化 缺乏客观指标 引入眼动熵指数
与正常驾驶重叠 正常驾驶也包含思维活动 动态基线对比
实时性要求 需要在数秒内检测 短时窗熵计算

眼动熵指数理论

论文:Driver Cognitive Distraction Detection based on eye movement behavior and integration of multi-view space-channel feature

来源: Expert Systems with Applications, 2025

核心创新:
将信息熵理论引入眼动分析,量化眼动规律性,认知分心时眼动熵值显著升高。

熵计算公式:

1
2
3
4
5
6
H(X) = -Σ p(xi) * log2(p(xi))

其中:
- X: 眼动状态序列
- p(xi): 状态i的出现概率
- H(X): 眼动熵(越高表示越随机)

三种熵指标:

指标 定义 认知分心表现
空间熵 视线落点分布熵 熵值升高,视线分布更随机
时间熵 注视时长分布熵 熵值升高,注视时长波动大
转移熵 视线转移序列熵 熵值升高,转移模式更混乱

代码实现

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
"""
眼动熵指数计算模块

核心算法:
1. 空间熵(Spatial Entropy)
2. 时间熵(Temporal Entropy)
3. 转移熵(Transition Entropy)

依赖:numpy, scipy
"""

import numpy as np
from scipy.stats import entropy
from typing import List, Tuple, Dict
from collections import Counter

class EyeMovementEntropy:
"""
眼动熵指数计算器

输入:
gaze_positions: 视线位置序列 [(x, y), ...]
fixation_durations: 注视时长序列 [t1, t2, ...]
time_window: 分析窗口(秒)

输出:
spatial_entropy: 空间熵
temporal_entropy: 时间熵
transition_entropy: 转移熵
composite_score: 综合熵得分
"""

# AOI划分(Area of Interest)
AOI_GRID = {
'road_center': (0.4, 0.6, 0.3, 0.7), # 道路中心区域
'left_mirror': (0.0, 0.2, 0.3, 0.5),
'right_mirror': (0.8, 1.0, 0.3, 0.5),
'dashboard': (0.3, 0.7, 0.0, 0.3),
'top': (0.3, 0.7, 0.7, 1.0),
}

def __init__(self, time_window: float = 30.0):
"""
初始化

Args:
time_window: 分析窗口(秒)
"""
self.time_window = time_window

def calculate(
self,
gaze_positions: np.ndarray,
fixation_durations: np.ndarray,
timestamps: np.ndarray
) -> Dict[str, float]:
"""
计算眼动熵指标

Args:
gaze_positions: 视线位置 (N, 2), 归一化到0-1
fixation_durations: 注视时长 (N,), 单位秒
timestamps: 时间戳 (N,), 单位秒

Returns:
entropy_dict: 熵指标字典
"""
# 1. 空间熵
spatial_ent = self._spatial_entropy(gaze_positions)

# 2. 时间熵
temporal_ent = self._temporal_entropy(fixation_durations)

# 3. 转移熵
transition_ent = self._transition_entropy(gaze_positions)

# 4. 综合得分(加权)
composite = 0.4 * spatial_ent + 0.3 * temporal_ent + 0.3 * transition_ent

return {
'spatial_entropy': spatial_ent,
'temporal_entropy': temporal_ent,
'transition_entropy': transition_ent,
'composite_score': composite
}

def _spatial_entropy(self, positions: np.ndarray, grid_size: int = 8) -> float:
"""
计算空间熵

方法:将视野划分为grid_size×grid_size网格,
计算视线落入各网格的概率分布,然后计算熵
"""
# 网格划分
grid_x = np.floor(positions[:, 0] * grid_size).astype(int)
grid_y = np.floor(positions[:, 1] * grid_size).astype(int)

# 边界处理
grid_x = np.clip(grid_x, 0, grid_size - 1)
grid_y = np.clip(grid_y, 0, grid_size - 1)

# 网格索引
grid_indices = grid_x * grid_size + grid_y

# 频率统计
counter = Counter(grid_indices)
total = len(grid_indices)

# 概率分布
probabilities = np.array([counter[i] / total for i in range(grid_size ** 2)])

# 去除零值
probabilities = probabilities[probabilities > 0]

# 计算熵
spatial_ent = entropy(probabilities, base=2)

# 归一化到0-1
max_entropy = np.log2(grid_size ** 2)
normalized = spatial_ent / max_entropy

return normalized

def _temporal_entropy(self, durations: np.ndarray, bins: int = 10) -> float:
"""
计算时间熵

方法:将注视时长划分为bins个区间,
计算各区间频率分布的熵
"""
# 直方图统计
hist, _ = np.histogram(durations, bins=bins)

# 频率
probabilities = hist / hist.sum()

# 去除零值
probabilities = probabilities[probabilities > 0]

# 计算熵
temporal_ent = entropy(probabilities, base=2)

# 归一化
max_entropy = np.log2(bins)
normalized = temporal_ent / max_entropy

return normalized

def _transition_entropy(self, positions: np.ndarray) -> float:
"""
计算转移熵

方法:统计视线在AOI之间的转移模式,
计算转移序列的熵
"""
# AOI分配
aoi_sequence = self._assign_aoi(positions)

# 转移序列
transitions = []
for i in range(len(aoi_sequence) - 1):
transition = (aoi_sequence[i], aoi_sequence[i + 1])
transitions.append(transition)

if len(transitions) == 0:
return 0.0

# 转移频率
counter = Counter(transitions)
total = len(transitions)

# 概率分布
probabilities = np.array([count / total for count in counter.values()])

# 计算熵
transition_ent = entropy(probabilities, base=2)

# 归一化(理论最大熵取决于转移数)
max_entropy = np.log2(len(counter))
if max_entropy > 0:
normalized = transition_ent / max_entropy
else:
normalized = 0.0

return normalized

def _assign_aoi(self, positions: np.ndarray) -> List[str]:
"""
分配AOI标签

Args:
positions: 视线位置 (N, 2)

Returns:
aoi_labels: AOI标签列表
"""
aoi_labels = []

for x, y in positions:
assigned = 'other'
for aoi_name, (x1, x2, y1, y2) in self.AOI_GRID.items():
if x1 <= x <= x2 and y1 <= y <= y2:
assigned = aoi_name
break
aoi_labels.append(assigned)

return aoi_labels


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

方法:
1. 实时计算眼动熵
2. 动态基线对比
3. 阈值判定
"""

# 检测阈值(来自论文实验数据)
THRESHOLDS = {
'spatial_entropy_high': 0.6, # 空间熵过高
'composite_high': 0.55, # 综合熵过高
'window_sec': 30.0 # 分析窗口
}

def __init__(self):
self.entropy_calculator = EyeMovementEntropy()
self.baseline = None # 动态基线

def update_baseline(self, positions: np.ndarray, durations: np.ndarray, timestamps: np.ndarray):
"""
更新基线(正常驾驶时)
"""
entropy_dict = self.entropy_calculator.calculate(positions, durations, timestamps)
self.baseline = entropy_dict

def detect(self, positions: np.ndarray, durations: np.ndarray, timestamps: np.ndarray) -> Dict:
"""
检测认知分心

Returns:
result: {
'is_distracted': bool,
'entropy_scores': dict,
'deviation': float
}
"""
# 计算当前熵
current = self.entropy_calculator.calculate(positions, durations, timestamps)

# 基线对比
if self.baseline is not None:
deviation = current['composite_score'] - self.baseline['composite_score']
else:
deviation = 0.0

# 判定
is_distracted = current['composite_score'] > self.THRESHOLDS['composite_high']

return {
'is_distracted': is_distracted,
'entropy_scores': current,
'deviation': deviation
}


# 测试
if __name__ == "__main__":
# 模拟正常驾驶数据
np.random.seed(42)
normal_positions = np.random.normal(0.5, 0.1, (100, 2)) # 集中在道路中心
normal_durations = np.random.normal(0.3, 0.05, 100) # 注视时长稳定
normal_timestamps = np.arange(100) * 0.1

# 模拟认知分心数据
distracted_positions = np.random.uniform(0, 1, (100, 2)) # 视线随机分布
distracted_durations = np.random.uniform(0.1, 0.8, 100) # 注视时长波动大
distracted_timestamps = np.arange(100) * 0.1

# 检测
detector = CognitiveDistractionDetector()

# 建立基线
detector.update_baseline(normal_positions, normal_durations, normal_timestamps)

# 正常驾驶检测
normal_result = detector.detect(normal_positions, normal_durations, normal_timestamps)
print(f"正常驾驶 - 综合熵: {normal_result['entropy_scores']['composite_score']:.3f}, "
f"是否分心: {normal_result['is_distracted']}")

# 认知分心检测
distracted_result = detector.detect(distracted_positions, distracted_durations, distracted_timestamps)
print(f"认知分心 - 综合熵: {distracted_result['entropy_scores']['composite_score']:.3f}, "
f"是否分心: {distracted_result['is_distracted']}, "
f"偏差: {distracted_result['deviation']:.3f}")

性能评估(论文Table 3):

数据集 样本数 空间熵准确率 时间熵准确率 综合准确率
正常驾驶 500 92.3% 88.5% 90.4%
认知分心 500 89.7% 91.2% 90.5%
总体 1000 91.0% 89.9% 90.5%

与传统方法对比

方法 检测线索 准确率 时延 Euro NCAP适配
眼动熵方法 视线分布规律性 90.5% 5-10s ✅ 完全满足
PERCLOS方法 眼睑闭合度 85% 60s 🟡 仅适用疲劳
视线偏离方法 视线离路时间 88% 3s 🟡 仅适用视觉分心
EEG方法 脑电波 95% 实时 ❌ 侵入性太强

实战部署要点

1. 数据采集配置

参数 推荐值 说明
眼动采样率 ≥60Hz 捕捉微观眼动
注视检测阈值 >100ms 最小注视时长
分析窗口 30-60秒 熵计算窗口
基线更新周期 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
# 阈值调优代码
def optimize_thresholds(validation_data):
"""
阈值优化

方法:网格搜索最大化F1分数
"""
best_f1 = 0
best_threshold = None

for spatial_th in np.arange(0.4, 0.8, 0.05):
for composite_th in np.arange(0.4, 0.7, 0.05):
# 计算
tp, fp, tn, fn = evaluate(validation_data, spatial_th, composite_th)

# F1分数
precision = tp / (tp + fp) if (tp + fp) > 0 else 0
recall = tp / (tp + fn) if (tp + fn) > 0 else 0
f1 = 2 * precision * recall / (precision + recall) if (precision + recall) > 0 else 0

if f1 > best_f1:
best_f1 = f1
best_threshold = {'spatial': spatial_th, 'composite': composite_th}

return best_threshold, best_f1

IMS开发启示

功能实现路线

阶段 功能 周期 输出
第一阶段 空间熵计算 1周 视线分布分析模块
第二阶段 时间熵计算 1周 注视时长分析模块
第三阶段 转移熵计算 1周 AOI转移分析模块
第四阶段 综合判定 1周 多熵融合检测器
第五阶段 动态基线 1周 自适应阈值系统

验证标准

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
### COG-01 认知分心检测测试

**前置条件:**
- 驾驶员正常坐姿,无视觉遮挡
- 眼动追踪系统采样率≥60Hz
- 基线已建立(正常驾驶5分钟)

**测试步骤:**
1. 正常驾驶5分钟(建立基线)
2. 执行认知任务(心算、记忆)5分钟
3. 记录熵值变化和检测结果

**判定条件:**
| 测试项 | 通过条件 | 失败条件 |
|--------|---------|---------|
| 综合熵检测准确率 | ≥90% | <90% |
| 检测时延 | ≤10s | >10s |
| 误报率(正常驾驶) | ≤5% | >5% |
| 漏报率(认知分心) | ≤10% | >10% |

**预期输出:**

[00:05:00] INFO: 基线建立,综合熵: 0.42
[00:06:30] WARN: 检测到认知分心,综合熵: 0.68,偏差: 0.26
[00:06:40] INFO: 告警发出,时延: 10s

1

参考资料

  1. 论文: Zuo et al., “Driver Cognitive Distraction Detection based on eye movement behavior”, Expert Systems with Applications, 2025
  2. Euro NCAP: DSM Test Protocol v1.0, Section 5.3
  3. Smart Eye: Eye Tracking Integration Guide
  4. 开源代码: https://github.com/example/eye-entropy

总结: 眼动熵指数是Euro NCAP 2026认知分心检测的核心技术,通过量化视线分布规律性,实现90%以上检测准确率。建议优先实现空间熵和时间熵,再融合转移熵形成综合判定。动态基线是关键,需要持续更新以适应个体差异。


认知分心检测新突破:眼动熵指数量化方法
https://dapalm.com/2026/08/09/2026-08-09-Cognitive-Distraction-Entropy-Detection/
作者
Mars
发布于
2026年8月9日
许可协议