认知分心检测突破:眼动熵与脑电融合的前沿研究

问题背景

认知分心(Cognitive Distraction)是 DMS 最后的难关:

分心类型 检测难度 现状
视觉分心 低 ✅ 已量产(视线偏离)
手动分心 低 ✅ 已量产(手机检测)
认知分心 极高 ❌ 待突破

认知分心的核心难点:

  • 驾驶员视线可能仍然看向道路
  • 手部动作正常
  • 仅表现为”走神”、”心不在焉”
  • 传统指标(PERCLOS、视线偏离)无法检测

最新研究进展(2025-2026)

1. 眼动熵(Gaze Entropy)方法

核心思想: 认知分心时,眼动模式变得”规则化”(熵降低)

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
"""
眼动熵认知分心检测

理论基础:
- 正常驾驶:眼动随机性高(扫描道路)
- 认知分心:眼动模式固定(凝视某点)
- 通过计算眼动熵量化分心程度
"""

import numpy as np
from scipy import stats

class GazeEntropyDetector:
"""眼动熵分心检测器"""

def __init__(self, window_size: int = 300):
"""
Args:
window_size: 时间窗口(帧数,约10秒@30fps)
"""
self.window_size = window_size
self.gaze_history = []

def calculate_entropy(self, gaze_points: np.ndarray) -> dict:
"""
计算眼动熵

Args:
gaze_points: 视线点序列 (N, 2)

Returns:
各种熵指标
"""
# 1. 空间熵(Spatial Entropy)
spatial_entropy = self._spatial_entropy(gaze_points)

# 2. 转移熵(Transition Entropy)
transition_entropy = self._transition_entropy(gaze_points)

# 3. 条件熵(Conditional Entropy)
conditional_entropy = self._conditional_entropy(gaze_points)

# 综合熵指标
combined_entropy = np.mean([
spatial_entropy,
transition_entropy,
conditional_entropy
])

return {
"spatial_entropy": spatial_entropy,
"transition_entropy": transition_entropy,
"conditional_entropy": conditional_entropy,
"combined_entropy": combined_entropy,
"is_distracted": combined_entropy < 0.7 # 熵降低表示分心
}

def _spatial_entropy(self, points: np.ndarray) -> float:
"""
空间熵:视线点空间分布的不确定性

计算方法:
1. 将视野划分为网格
2. 计算每个网格的频率
3. 使用香农熵
"""
# 归一化到 [0, 1]
points_norm = (points - points.min(axis=0)) / (
points.max(axis=0) - points.min(axis=0) + 1e-6
)

# 离散化(16x16 网格)
grid_size = 16
grid = np.zeros((grid_size, grid_size))

for p in points_norm:
i = int(p[0] * (grid_size - 1))
j = int(p[1] * (grid_size - 1))
grid[i, j] += 1

# 计算频率
grid = grid / grid.sum()

# 香农熵
entropy = -np.sum(grid[grid > 0] * np.log2(grid[grid > 0] + 1e-10))

# 归一化到 [0, 1]
max_entropy = np.log2(grid_size * grid_size)
return entropy / max_entropy

def _transition_entropy(self, points: np.ndarray) -> float:
"""
转移熵:眼动序列的转移模式不确定性

计算方法:
1. 离散化视线点为区域标签
2. 计算转移概率矩阵
3. 计算转移熵
"""
# K-means 聚类离散化
from sklearn.cluster import KMeans

n_clusters = 8
kmeans = KMeans(n_clusters=n_clusters, random_state=42)
labels = kmeans.fit_predict(points)

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

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

# 转移熵
row_entropy = []
for row in transition_matrix:
if row.sum() > 0:
ent = -np.sum(row[row > 0] * np.log2(row[row > 0] + 1e-10))
row_entropy.append(ent)

return np.mean(row_entropy) / np.log2(n_clusters)

def _conditional_entropy(self, points: np.ndarray) -> float:
"""
条件熵:给定当前位置,下一个位置的不确定性
"""
# 简化实现:使用自相关分析
from statsmodels.tsa.stattools import acf

# 计算 x 和 y 方向的自相关
x = points[:, 0]
y = points[:, 1]

x_acf = acf(x, nlags=10, fft=True)
y_acf = acf(y, nlags=10, fft=True)

# 高自相关表示低随机性(低熵)
# 返回 1 - 平均自相关
avg_autocorr = np.mean(np.abs(x_acf[1:]) + np.abs(y_acf[1:])) / 2

return 1 - avg_autocorr


# 测试示例
if __name__ == "__main__":
detector = GazeEntropyDetector()

# 模拟正常驾驶眼动(高随机性)
normal_gaze = np.random.randn(300, 2) * 10 + np.array([5, 5])

# 模拟认知分心眼动(凝视单点,低随机性)
distracted_gaze = np.random.randn(300, 2) * 0.5 + np.array([5, 5])

normal_result = detector.calculate_entropy(normal_gaze)
distracted_result = detector.calculate_entropy(distracted_gaze)

print(f"正常驾驶综合熵: {normal_result['combined_entropy']:.3f}")
print(f"认知分心综合熵: {distracted_result['combined_entropy']:.3f}")
print(f"正常驾驶是否分心: {normal_result['is_distracted']}")
print(f"认知分心是否分心: {distracted_result['is_distracted']}")

2. EEG 辅助检测

前沿研究:单通道耳内 EEG

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
"""
耳内 EEG 认知分心检测

研究来源:
- Predicting driver distraction using a single channel ear EEG
- bioRxiv 2026.01.24

核心发现:
- 认知分心在眼动指标变化前就出现在 EEG 中
- Theta/Alpha 波段是最佳指标
"""

class EEGDistractionDetector:
"""EEG 分心检测器"""

def __init__(self):
# EEG 频段定义
self.frequency_bands = {
"delta": (0.5, 4),
"theta": (4, 8),
"alpha": (8, 13),
"beta": (13, 30),
"gamma": (30, 100)
}

def analyze_eeg(self, eeg_signal: np.ndarray, fs: int = 250) -> dict:
"""
分析 EEG 信号

Args:
eeg_signal: EEG 时间序列
fs: 采样率

Returns:
各频段功率及分心判断
"""
# 1. 预处理
eeg_filtered = self._preprocess(eeg_signal, fs)

# 2. 功率谱密度
freqs, psd = self._compute_psd(eeg_filtered, fs)

# 3. 各频段功率
band_power = {}
for band_name, (low, high) in self.frequency_bands.items():
idx = np.where((freqs >= low) & (freqs <= high))
band_power[band_name] = np.mean(psd[idx])

# 4. 特征计算
theta_alpha_ratio = band_power["theta"] / (band_power["alpha"] + 1e-6)

# 5. 分心判断
# 认知分心时:Theta 增加,Alpha 降低
is_distracted = theta_alpha_ratio > 1.5

return {
"band_power": band_power,
"theta_alpha_ratio": theta_alpha_ratio,
"is_distracted": is_distracted,
"confidence": min(1.0, theta_alpha_ratio / 2.0)
}

def _preprocess(self, signal: np.ndarray, fs: int) -> np.ndarray:
"""EEG 预处理"""
from scipy import signal as sp_signal

# 带通滤波 0.5-50 Hz
b, a = sp_signal.butter(4, [0.5, 50], btype='band', fs=fs)
filtered = sp_signal.filtfilt(b, a, signal)

# 去除基线漂移
filtered = filtered - np.mean(filtered)

return filtered

def _compute_psd(self, signal: np.ndarray, fs: int) -> tuple:
"""计算功率谱密度"""
from scipy import signal as sp_signal

freqs, psd = sp_signal.welch(signal, fs, nperseg=min(256, len(signal)))
return freqs, psd


import numpy as np

# 测试示例
if __name__ == "__main__":
detector = EEGDistractionDetector()

# 模拟 EEG 信号(包含 theta 和 alpha)
fs = 250
t = np.linspace(0, 10, 10 * fs)

# 正常驾驶 EEG
normal_eeg = (
np.sin(2 * np.pi * 10 * t) * 10 + # Alpha
np.sin(2 * np.pi * 6 * t) * 5 + # Theta
np.random.randn(len(t)) * 2
)

# 认知分心 EEG(Theta 增强)
distracted_eeg = (
np.sin(2 * np.pi * 10 * t) * 5 + # Alpha 降低
np.sin(2 * np.pi * 6 * t) * 15 + # Theta 增加
np.random.randn(len(t)) * 2
)

normal_result = detector.analyze_eeg(normal_eeg, fs)
distracted_result = detector.analyze_eeg(distracted_eeg, fs)

print(f"正常驾驶 Theta/Alpha: {normal_result['theta_alpha_ratio']:.2f}")
print(f"认知分心 Theta/Alpha: {distracted_result['theta_alpha_ratio']:.2f}")

Euro NCAP 2026 要求

认知分心检测场景

场景 ID 描述 检测时限 警告等级
CD-01 长时间凝视单一区域 ≤ 5s 一级
CD-02 眼动模式异常固定 ≤ 10s 二级
CD-03 驾驶员”走神”表现 ≤ 15s 一级

IMS 开发启示

技术路线

阶段 方案 可行性 时间节点
近期 眼动熵分析 高 2026 Q2
中期 眼动+行为融合 中 2026 Q4
远期 耳内 EEG(可选) 低 2027+

算法集成

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
"""
IMS 认知分心检测模块
"""

class CognitiveDistractionModule:
"""认知分心检测模块"""

def __init__(self):
self.gaze_detector = GazeEntropyDetector()
self.eeg_detector = EEGDistractionDetector() # 可选

self.gaze_history = []

def detect(self, gaze_point: tuple, eeg_signal: np.ndarray = None) -> dict:
"""
综合检测

Args:
gaze_point: 当前视线点 (x, y)
eeg_signal: EEG 信号(可选)

Returns:
分心检测结果
"""
# 1. 更新眼动历史
self.gaze_history.append(gaze_point)
if len(self.gaze_history) > 300:
self.gaze_history = self.gaze_history[-300:]

# 2. 眼动熵分析
if len(self.gaze_history) >= 150:
gaze_result = self.gaze_detector.calculate_entropy(
np.array(self.gaze_history)
)
else:
gaze_result = {"is_distracted": False, "combined_entropy": 1.0}

# 3. EEG 分析(如果有)
eeg_result = None
if eeg_signal is not None:
eeg_result = self.eeg_detector.analyze_eeg(eeg_signal)

# 4. 融合判断
if eeg_result is not None:
# 双模态融合
is_distracted = gaze_result["is_distracted"] or eeg_result["is_distracted"]
confidence = (gaze_result.get("combined_entropy", 1.0) +
eeg_result.get("confidence", 0.5)) / 2
else:
is_distracted = gaze_result["is_distracted"]
confidence = 1 - gaze_result.get("combined_entropy", 0.5)

return {
"is_distracted": is_distracted,
"confidence": confidence,
"gaze_entropy": gaze_result.get("combined_entropy"),
"eeg_available": eeg_result is not None
}

总结

认知分心检测关键要点:

  1. 眼动熵方法:通过量化眼动随机性检测分心
  2. EEG 辅助:可在眼动变化前检测到分心
  3. 实时性挑战:需要至少 5 秒数据窗口
  4. 误报控制:多指标融合降低误报
  5. 法规合规:Euro NCAP 2026 开始要求

IMS 集成建议:

  • 优先部署眼动熵算法
  • 设计长时间数据缓冲
  • 准备多级警告机制
  • 可选集成 EEG(高端车型)

参考资料:

  1. Driver Cognitive Distraction Detection Based on Eye Movement Behavior (Springer 2026)
  2. Predicting driver distraction using a single channel ear EEG (bioRxiv 2026)
  3. Euro NCAP 2026 Cognitive Distraction Requirements