认知分心检测突破:眼动熵与驾驶认知负荷评估

认知分心检测突破:眼动熵与驾驶认知负荷评估

来源: Springer Nature + Euro NCAP研究
发布时间: 2026年4月
核心价值: 认知分心是Euro NCAP 2026最难检测项,眼动熵是最有前景方案


核心洞察

认知分心vs视觉分心:

特征 视觉分心 认知分心
眼睛方向 偏离道路 仍在道路
检测难度
危险程度 中高
典型场景 看手机 走神、深思

眼动熵检测原理:

  • 认知负荷增加时,眼动变得不规律
  • 熵值升高表示随机性增加
  • 视线”凝视”模式减少

一、认知分心概念

1.1 分心类型定义

类型 定义 示例
视觉分心 眼睛离开道路 看手机、看导航
手动分心 手离开方向盘 调空调、拿东西
认知分心 心智离开驾驶 走神、电话交谈、思考问题

1.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
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
"""
认知分心生理特征分析
"""

import numpy as np
from dataclasses import dataclass
from typing import List, Tuple
from enum import Enum

class CognitiveState(Enum):
"""认知状态"""
FOCUSED = "focused" # 专注
MILD_DISTRACTED = "mild" # 轻度分心
MODERATE_DISTRACTED = "moderate" # 中度分心
SEVERE_DISTRACTED = "severe" # 严重分心

@dataclass
class EyeMovementFeatures:
"""眼动特征"""
# 注视特征
fixation_count: int # 注视次数
avg_fixation_duration: float # 平均注视时长 (ms)
fixation_dispersion: float # 注视分散度

# 扫视特征
saccade_count: int # 扫视次数
avg_saccade_amplitude: float # 平均扫视幅度 (度)
saccade_velocity: float # 扫视速度 (度/s)

# 熵特征
gaze_entropy: float # 眼动熵 (空间)
transition_entropy: float # 转移熵 (时间)

# 瞳孔特征
pupil_diameter_mean: float # 平均瞳孔直径 (mm)
pupil_diameter_var: float # 瞳孔直径方差

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

检测原理:
1. 眼动熵增加(随机性增强)
2. 注视分散(注意力不集中)
3. 扫视模式变化
4. 瞳孔直径变化(认知负荷)
"""

def __init__(self):
# 熵阈值
self.entropy_thresholds = {
'focused': 1.5,
'mild': 2.0,
'moderate': 2.5,
'severe': 3.0
}

# 注视分散阈值
self.dispersion_thresholds = {
'focused': 100, # 像素
'mild': 150,
'moderate': 200,
'severe': 250
}

def detect(self, features: EyeMovementFeatures) -> Tuple[CognitiveState, dict]:
"""
检测认知分心

Args:
features: 眼动特征

Returns:
(state, info)
"""
# 计算综合得分
entropy_score = self._entropy_score(features.gaze_entropy)
dispersion_score = self._dispersion_score(features.fixation_dispersion)
fixation_score = self._fixation_score(features.avg_fixation_duration)
pupil_score = self._pupil_score(features.pupil_diameter_var)

# 加权综合
weights = {
'entropy': 0.4,
'dispersion': 0.3,
'fixation': 0.2,
'pupil': 0.1
}

total_score = (
entropy_score * weights['entropy'] +
dispersion_score * weights['dispersion'] +
fixation_score * weights['fixation'] +
pupil_score * weights['pupil']
)

# 分类
if total_score < 0.25:
state = CognitiveState.FOCUSED
elif total_score < 0.5:
state = CognitiveState.MILD_DISTRACTED
elif total_score < 0.75:
state = CognitiveState.MODERATE_DISTRACTED
else:
state = CognitiveState.SEVERE_DISTRACTED

info = {
'state': state.value,
'total_score': total_score,
'entropy_score': entropy_score,
'dispersion_score': dispersion_score,
'fixation_score': fixation_score,
'pupil_score': pupil_score,
}

return state, info

def _entropy_score(self, entropy: float) -> float:
"""熵得分 (0-1)"""
if entropy < self.entropy_thresholds['focused']:
return 0.0
elif entropy < self.entropy_thresholds['mild']:
return 0.25
elif entropy < self.entropy_thresholds['moderate']:
return 0.5
elif entropy < self.entropy_thresholds['severe']:
return 0.75
else:
return 1.0

def _dispersion_score(self, dispersion: float) -> float:
"""分散度得分"""
if dispersion < self.dispersion_thresholds['focused']:
return 0.0
elif dispersion < self.dispersion_thresholds['mild']:
return 0.25
elif dispersion < self.dispersion_thresholds['moderate']:
return 0.5
elif dispersion < self.dispersion_thresholds['severe']:
return 0.75
else:
return 1.0

def _fixation_score(self, avg_duration: float) -> float:
"""注视时长得分"""
# 认知分心时注视时长变短
if avg_duration > 300: # ms
return 0.0
elif avg_duration > 200:
return 0.25
elif avg_duration > 150:
return 0.5
elif avg_duration > 100:
return 0.75
else:
return 1.0

def _pupil_score(self, pupil_var: float) -> float:
"""瞳孔方差得分"""
# 认知负荷增加时瞳孔直径波动
if pupil_var < 0.1:
return 0.0
elif pupil_var < 0.2:
return 0.25
elif pupil_var < 0.3:
return 0.5
elif pupil_var < 0.4:
return 0.75
else:
return 1.0


# 实际测试
if __name__ == "__main__":
detector = CognitiveDistractionDetector()

# 场景1:专注驾驶
features_focused = EyeMovementFeatures(
fixation_count=30,
avg_fixation_duration=350,
fixation_dispersion=80,
saccade_count=29,
avg_saccade_amplitude=5,
saccade_velocity=100,
gaze_entropy=1.2,
transition_entropy=0.8,
pupil_diameter_mean=4.0,
pupil_diameter_var=0.05
)

state, info = detector.detect(features_focused)
print("=== 场景1:专注驾驶 ===")
print(f"状态: {state.value}")
print(f"综合得分: {info['total_score']:.2f}")

# 场景2:认知分心
features_distracted = EyeMovementFeatures(
fixation_count=50,
avg_fixation_duration=120,
fixation_dispersion=250,
saccade_count=49,
avg_saccade_amplitude=8,
saccade_velocity=150,
gaze_entropy=3.2,
transition_entropy=2.5,
pupil_diameter_mean=4.5,
pupil_diameter_var=0.4
)

state, info = detector.detect(features_distracted)
print("\n=== 场景2:认知分心 ===")
print(f"状态: {state.value}")
print(f"综合得分: {info['total_score']:.2f}")

二、眼动熵计算

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
"""
眼动熵计算
"""

import numpy as np
from typing import List, Tuple
from collections import Counter
import math

class GazeEntropyCalculator:
"""
眼动熵计算器

熵类型:
1. 空间熵:视线位置的随机性
2. 转移熵:视线转移的规律性
"""

def __init__(self,
grid_size: int = 10,
smooth_window: int = 5):
"""
初始化

Args:
grid_size: 网格大小(将视野划分为grid_size x grid_size)
smooth_window: 平滑窗口大小
"""
self.grid_size = grid_size
self.smooth_window = smooth_window

def calculate_spatial_entropy(self,
gaze_positions: List[Tuple[float, float]]) -> float:
"""
计算空间熵

Args:
gaze_positions: 视线位置列表 [(x, y), ...]
x, y 归一化到 [0, 1]

Returns:
熵值 (bits)
"""
if len(gaze_positions) == 0:
return 0.0

# 将位置量化到网格
grid_positions = []
for x, y in gaze_positions:
grid_x = min(int(x * self.grid_size), self.grid_size - 1)
grid_y = min(int(y * self.grid_size), self.grid_size - 1)
grid_positions.append((grid_x, grid_y))

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

# 计算熵
entropy = 0.0
for count in counter.values():
p = count / total
entropy -= p * math.log2(p)

return entropy

def calculate_transition_entropy(self,
gaze_positions: List[Tuple[float, float]]) -> float:
"""
计算转移熵

转移熵衡量视线转移的规律性

Args:
gaze_positions: 视线位置列表

Returns:
转移熵 (bits)
"""
if len(gaze_positions) < 2:
return 0.0

# 量化位置
grid_positions = []
for x, y in gaze_positions:
grid_x = min(int(x * self.grid_size), self.grid_size - 1)
grid_y = min(int(y * self.grid_size), self.grid_size - 1)
grid_positions.append((grid_x, grid_y))

# 统计转移
transitions = Counter()
for i in range(len(grid_positions) - 1):
from_pos = grid_positions[i]
to_pos = grid_positions[i + 1]
transitions[(from_pos, to_pos)] += 1

# 计算转移熵
total_transitions = len(grid_positions) - 1
transition_entropy = 0.0

for count in transitions.values():
p = count / total_transitions
transition_entropy -= p * math.log2(p)

return transition_entropy

def calculate_gaze_entropy_rate(self,
gaze_positions: List[Tuple[float, float]]) -> float:
"""
计算眼动熵率

熵率 = 空间熵 + 转移熵

Args:
gaze_positions: 视线位置列表

Returns:
熵率
"""
spatial = self.calculate_spatial_entropy(gaze_positions)
transition = self.calculate_transition_entropy(gaze_positions)

return spatial + transition * 0.5 # 加权组合


# 实际测试
if __name__ == "__main__":
calculator = GazeEntropyCalculator(grid_size=10)

# 场景1:规律眼动(专注驾驶)
focused_gaze = [(0.5, 0.5) for _ in range(50)] # 注视中心
spatial = calculator.calculate_spatial_entropy(focused_gaze)
transition = calculator.calculate_transition_entropy(focused_gaze)
print(f"专注驾驶: 空间熵={spatial:.2f}, 转移熵={transition:.2f}")

# 场景2:随机眼动(认知分心)
distracted_gaze = [(np.random.rand(), np.random.rand()) for _ in range(50)]
spatial = calculator.calculate_spatial_entropy(distracted_gaze)
transition = calculator.calculate_transition_entropy(distracted_gaze)
print(f"认知分心: 空间熵={spatial:.2f}, 转移熵={transition:.2f}")

# 场景3:中等规律
mixed_gaze = [(0.5 + np.random.randn() * 0.1, 0.5 + np.random.randn() * 0.1) for _ in range(50)]
spatial = calculator.calculate_spatial_entropy(mixed_gaze)
transition = calculator.calculate_transition_entropy(mixed_gaze)
print(f"混合状态: 空间熵={spatial:.2f}, 转移熵={transition:.2f}")

三、IMS开发建议

3.1 检测策略

方案 准确率 实时性 复杂度
眼动熵 85%
瞳孔测量 75%
生理信号 90%
多模态融合 92%

3.2 Euro NCAP合规

要求 眼动熵方案 状态
检测认知分心 ✅ 支持 合规
区分疲劳vs分心 ⚠️ 需结合其他指标 部分合规
实时检测 ✅ <30ms 合规
误报率<5% ⚠️ 需优化 待验证

四、总结

4.1 核心发现

  1. 眼动熵是认知分心检测最有前景方案
  2. 熵值升高表示认知负荷增加
  3. 需结合多特征提高准确率
  4. 瞳孔直径是辅助指标

4.2 未来方向

  • 深度学习自动提取眼动特征
  • 多模态融合(EEG+眼动)
  • 个性化阈值学习

参考链接:

  • Springer: Driver Cognitive Distraction Detection
  • Euro NCAP 2026 Protocol
  • Nature: Eye Movement and Cognitive Load

认知分心检测突破:眼动熵与驾驶认知负荷评估
https://dapalm.com/2026/04/24/2026-04-24-cognitive-distraction-gaze-entropy-detection/
作者
Mars
发布于
2026年4月24日
许可协议