EyeCue论文解读:基于眼动-视频融合的认知分心检测

论文信息

  • 标题: EyeCue: Driver Cognitive Distraction Detection via Gaze-Empowered Egocentric Video Understanding
  • 作者: Lang Zhang, JinYi Yoon, Matthew Corbett, Abhijit Sarkar, Bo Ji
  • 机构: Virginia Tech, Inha University, Army Cyber Institute
  • 会议: IJCAI 2026
  • 链接: arXiv:2605.07859
  • 代码: GitHub: EyeCue

核心问题:认知分心检测的困境

认知分心 vs 视觉分心 vs 手动分心

类型 定义 检测难度 示例
手动分心 手离开方向盘 ⭐ 简单 拿手机、吃东西
视觉分心 眼睛离开道路 ⭐⭐ 中等 看导航、看仪表盘
认知分心 思想游离、注意力不集中 ⭐⭐⭐⭐⭐ 困难 发呆、走神、思考其他事情

核心挑战:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 认知分心的隐蔽性示例
# 驾驶员看似"正常",实际已分心

def check_driver_state():
"""
认知分心的矛盾性:
- 眼睛盯着道路(视觉正常)
- 手握方向盘(手动正常)
- 但思想已游离(认知异常)
"""
visual_attention = True # ✅ 看着道路
manual_attention = True # ✅ 手在方向盘
cognitive_attention = False # ❌ 思想游离

# 传统DMS无法检测!
if visual_attention and manual_attention:
return "正常" # 错误判断!
else:
return "分心"

数据支撑:

  • 分心驾驶导致约30%的交通死亡事故(2023年美国3,275人死亡)
  • 经济损失:98亿美元基础设施维护成本
  • 认知分心是最难检测的类型,现有研究严重不足

核心创新:眼动-视觉上下文交互建模

关键洞察

认知分心反映在眼动与环境上下文的交互模式中

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
# 正常驾驶 vs 认知分心的眼动模式差异

class GazeContextInteraction:
"""
论文核心洞察:认知分心 → 眼动-上下文交互异常

正常驾驶:
- 眼动广泛分布,覆盖多个任务相关区域
- 频繁扫描道路、行人、交通标志

认知分心:
- 眼动局限于特定区域("注视僵化")
- 与任务相关对象的交互减少
"""

def analyze_gaze_pattern(self, gaze_sequence, video_context):
"""
分析眼动-上下文交互

Args:
gaze_sequence: 眼动序列 [(x1,y1), (x2,y2), ...]
video_context: 第一人称视频帧序列

Returns:
interaction_score: 交互质量评分
"""
# 1. 提取眼动注视点对应的视觉区域
gaze_regions = self.extract_gaze_regions(gaze_sequence, video_context)

# 2. 分析眼动分布广度
gaze_spread = self.calculate_spatial_spread(gaze_sequence)

# 3. 分析任务相关对象交互频率
task_object_interaction = self.count_task_object_fixations(gaze_regions)

# 4. 认知状态判断
if gaze_spread < THRESHOLD and task_object_interaction < MIN_INTERACTION:
return "COGNITIVE_DISTRACTED"
else:
return "ATTENTIVE"

三大设计挑战

挑战 问题 EyeCue解决方案
C1:特征提取 如何从视频和眼动中提取全局+细粒度特征? 双编码器架构:视频编码器 + 眼动编码器
C2:多模态融合 如何有效融合眼动与视频信息? GDSQ模块:眼动驱动的语义查询
C3:数据稀缺 缺乏认知分心标注数据集 CogDrive数据集:3,662样本跨场景标注

架构详解:EyeCue框架


graph TB
    subgraph 输入层
        A[第一人称视频] --> B[视频预处理]
        C[眼动坐标序列] --> D[眼动嵌入]
    end
    
    subgraph 编码器层
        B --> E[视频编码器
TimeSformer/VideoMAE] D --> F[眼动编码器
Lightweight Transformer] end subgraph 交互建模层 E --> G[视频patch tokens] F --> H[眼动特征tokens] C --> I[注视点选择] G --> I I --> J[GDSQ模块
交叉注意力] H --> J end subgraph 融合分类层 E --> K[视频CLS token] J --> L[语义CLS token] F --> M[眼动CLS token] K --> N[拼接] L --> N M --> N N --> O[MLP分类器] O --> P[认知状态: 分心/专注] end

核心模块代码实现

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
import torch
import torch.nn as nn
from transformers import VideoMAEModel, TimesformerModel

class EyeCue(nn.Module):
"""
EyeCue: 眼动驱动的认知分心检测框架

论文核心实现:眼动-视频上下文交互建模
"""

def __init__(self, config):
super().__init__()

# 视频编码器(论文使用TimeSformer-K600或VideoMAE-K400)
self.video_encoder = TimesformerModel.from_pretrained('timesformer-k600')
# 或: VideoMAEModel.from_pretrained('videomae-k400')

# 眼动编码器(轻量级Transformer)
self.gaze_encoder = GazeEncoder(
d_model=768, # 与视频编码器对齐
nhead=8,
num_layers=1 # 论文使用1层
)

# GDSQ模块:眼动驱动的语义查询
self.gdsq = GazeDrivenSemanticQuery(
d_model=768,
nhead=8,
num_layers=2 # 论文使用2层交叉注意力
)

# 分类头
self.classifier = nn.Sequential(
nn.Linear(768 * 3, 512), # 3个CLS token拼接
nn.ReLU(),
nn.Dropout(0.1),
nn.Linear(512, 2) # 二分类:分心/专注
)

def forward(self, video_frames, gaze_coords):
"""
前向传播

Args:
video_frames: [B, T, C, H, W] 第一人称视频帧
gaze_coords: [B, T, 2] 眼动坐标序列 (x, y)

Returns:
logits: [B, 2] 分类logits
"""
# 1. 视频编码
video_output = self.video_encoder(video_frames)
video_cls = video_output.last_hidden_state[:, 0] # [B, 768]
video_patches = video_output.last_hidden_state[:, 1:] # [B, num_patches, 768]

# 2. 眼动编码
gaze_cls, gaze_tokens = self.gaze_encoder(gaze_coords) # [B, 768], [B, T, 768]

# 3. GDSQ:眼动-视频交互建模
semantic_cls = self.gdsq(gaze_tokens, video_patches, gaze_coords)

# 4. 多模态融合与分类
fused = torch.cat([video_cls, gaze_cls, semantic_cls], dim=-1)
logits = self.classifier(fused)

return logits


class GazeEncoder(nn.Module):
"""
眼动编码器:将眼动坐标嵌入到语义空间
"""

def __init__(self, d_model, nhead, num_layers):
super().__init__()

# 坐标嵌入
self.coord_embedding = nn.Linear(2, d_model)

# 位置编码
self.pos_encoding = PositionalEncoding(d_model)

# Transformer编码器
encoder_layer = nn.TransformerEncoderLayer(d_model, nhead, batch_first=True)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)

# CLS token
self.cls_token = nn.Parameter(torch.randn(1, 1, d_model))

def forward(self, gaze_coords):
"""
Args:
gaze_coords: [B, T, 2] 眼动坐标

Returns:
cls_token: [B, d_model] 全局眼动表示
tokens: [B, T, d_model] 帧级眼动特征
"""
B, T, _ = gaze_coords.shape

# 嵌入眼动坐标
x = self.coord_embedding(gaze_coords) # [B, T, d_model]
x = self.pos_encoding(x)

# 添加CLS token
cls_tokens = self.cls_token.expand(B, -1, -1)
x = torch.cat([cls_tokens, x], dim=1) # [B, T+1, d_model]

# Transformer编码
x = self.transformer(x)

return x[:, 0], x[:, 1:] # CLS, tokens


class GazeDrivenSemanticQuery(nn.Module):
"""
GDSQ模块:眼动驱动的语义查询

核心思想:
- 眼动作为Query,查询视觉上下文
- 选择注视点附近的video patch tokens
- 通过交叉注意力建模眼动-视觉交互
"""

def __init__(self, d_model, nhead, num_layers):
super().__init__()

self.cross_attention_layers = nn.ModuleList([
nn.MultiheadAttention(d_model, nhead, batch_first=True)
for _ in range(num_layers)
])

self.norms = nn.ModuleList([
nn.LayerNorm(d_model) for _ in range(num_layers)
])

def forward(self, gaze_tokens, video_patches, gaze_coords):
"""
Args:
gaze_tokens: [B, T, d_model] 眼动特征
video_patches: [B, num_patches, d_model] 视频patch tokens
gaze_coords: [B, T, 2] 眼动坐标(用于选择patch)

Returns:
semantic_cls: [B, d_model] 语义表示
"""
# 1. 根据眼动坐标选择注视点附近的patch tokens
selected_patches = self.select_gaze_patches(video_patches, gaze_coords)
# selected_patches: [B, T, d_model] (论文使用h=1,每帧选1个patch)

# 2. 多层交叉注意力
x = gaze_tokens
for cross_attn, norm in zip(self.cross_attention_layers, self.norms):
# Query: 眼动特征
# Key/Value: 注视点附近的视觉patch
attn_out, _ = cross_attn(
query=x,
key=selected_patches,
value=selected_patches
)
x = norm(x + attn_out)

# 3. 池化得到语义CLS token
semantic_cls = x.mean(dim=1) # [B, d_model]

return semantic_cls

def select_gaze_patches(self, video_patches, gaze_coords):
"""
根据眼动坐标选择对应的video patch

Args:
video_patches: [B, num_patches, d_model]
gaze_coords: [B, T, 2] 归一化坐标 [0, 1]

Returns:
selected: [B, T, d_model]
"""
B, num_patches, d_model = video_patches.shape
T = gaze_coords.shape[1]

# 假设视频帧大小 H=W=14(patch数量14*14=196)
grid_size = int(num_patches ** 0.5)

# 将坐标转换为patch索引
patch_x = (gaze_coords[:, :, 0] * grid_size).long().clamp(0, grid_size-1)
patch_y = (gaze_coords[:, :, 1] * grid_size).long().clamp(0, grid_size-1)
patch_idx = patch_y * grid_size + patch_x # [B, T]

# 选择对应的patch
selected = torch.gather(
video_patches,
dim=1,
index=patch_idx.unsqueeze(-1).expand(-1, -1, d_model)
)

return selected


class PositionalEncoding(nn.Module):
"""位置编码"""

def __init__(self, d_model, max_len=5000):
super().__init__()
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
self.register_buffer('pe', pe.unsqueeze(0))

def forward(self, x):
return x + self.pe[:, :x.size(1)]


# ============ 使用示例 ============

if __name__ == "__main__":
# 模型配置
config = {
'video_encoder': 'timesformer-k600',
'd_model': 768,
'nhead': 8,
'num_gaze_layers': 1,
'num_gdsq_layers': 2
}

# 初始化模型
model = EyeCue(config)

# 模拟输入
batch_size = 4
num_frames = 16 # 论文使用16帧
video = torch.randn(batch_size, num_frames, 3, 224, 224)
gaze = torch.rand(batch_size, num_frames, 2) # 归一化眼动坐标

# 前向传播
logits = model(video, gaze)

# 预测
predictions = torch.argmax(logits, dim=-1)
print(f"预测结果: {predictions}")
# 0 = 专注, 1 = 认知分心

实验结果:超越所有基线

主要性能对比

模型 准确率 F1分数 备注
EyeCue (TimeSformer-K600) 74.38% 0.74 🏆 最佳
EyeCue (VideoMAE-K400) 73.12% 0.72 次优
GazeLLM 68.5% 0.67 训练-free
InternVideo2 66.8% 0.65 视频基础模型
TimeSformer (仅视频) 67.53% 0.66 消融实验
Gaze Encoder (仅眼动) 54.13% 0.52 消融实验
Heatmap-SVM 48.2% 0.45 传统方法

关键发现:

  1. 眼动+视频融合提升7%+:相比单一模态显著提升
  2. GDSQ模块贡献明显:单独使用GDSQ达到68.80%
  3. 跨场景泛化性强:不同道路/天气/时间均保持>70%准确率

消融实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 消融实验结果

ablation_results = {
"Video Encoder Only": 67.53,
"Gaze Encoder Only": 54.13,
"GDSQ Only": 68.80,
"Video + Gaze (Direct Fusion)": 72.31,
"Full EyeCue": 74.38
}

"""
结论:
1. 视频编码器贡献最大(场景上下文重要)
2. 眼动编码器单独性能差(缺乏上下文)
3. GDSQ模块有效建模交互(+1.27%)
4. 完整融合最佳(74.38%)
"""

超参数分析

1. 视频片段长度

帧数 准确率 说明
8帧 71.2% 时间上下文不足
16帧 74.38% 最佳平衡

2. 注视点patch数量(h)

h值 准确率 说明
h=1 74.38% 仅选择注视点所在patch,最佳
h=5 72.8% 引入周边区域,略降
h=9 71.5% 进一步扩大,稀释注视信息
h=25 68.2% 过大区域,失去中心性

洞察:

人类视觉的中央凹特性:h=1时,仅选择中央凹注视的单个patch,最精准捕捉驾驶员的视觉焦点。

场景分析

场景 准确率 样本数 分析
城市 72.1% 1,524 干扰因素多
高速 73.8% 892 环境单调,易走神
乡村 76.5% 682 场景简单,检测准确
白天 73.5% 2,012 视觉质量好
夜间 76.2% 842 目标少,干扰小
晴天 75.8% 2,156 最佳条件
雨天 71.3% 612 视觉质量下降

CogDrive数据集:填补认知分心数据空白

数据集构建

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
# CogDrive数据集构建流程

class CogDriveBuilder:
"""
跨数据集认知分心标注

来源数据集:
1. DR(eye)VE - 唯一已有认知分心标签
2. BDD-A - 大规模驾驶数据
3. DADA-2000 - 事故场景注意力
4. TrafficGaze - 交通场景眼动
"""

def __init__(self):
self.datasets = ['DR(eye)VE', 'BDD-A', 'DADA-2000', 'TrafficGaze']
self.annotation_protocol = self.load_protocol()

def annotate_clip(self, video_clip, gaze_sequence):
"""
认知分心标注协议(源自DR(eye)VE)

专注判断标准:
- 眼动广泛分布,覆盖任务相关区域
- 频繁扫描道路、行人、交通标志

分心判断标准:
- 眼动局限于特定区域
- 与任务相关对象交互少
- "凝视僵化"现象
"""
# 计算眼动分布广度
gaze_spread = self.calculate_spatial_distribution(gaze_sequence)

# 分析任务相关对象交互
task_interaction = self.analyze_task_object_fixations(
video_clip, gaze_sequence
)

# 双人独立标注 + 专家审核
label = self.expert_review(gaze_spread, task_interaction)

return label

数据集统计

数据集 专注样本 分心样本 总计 场景
DR(eye)VE 412 156 568 多道路类型
BDD-A 892 234 1,126 城市/高速
DADA-2000 756 198 954 事故场景
TrafficGaze 793 221 1,014 交通场景
总计 2,853 809 3,662 跨场景

数据集特点:

  • 多样化场景:城市/高速/乡村、白天/夜晚、晴天/雨天
  • 高质量标注:双人独立标注 + 专家审核,一致性>98%
  • 固定长度片段:16帧/片段,适合时序建模

IMS开发启示

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
# IMS认知分心检测部署建议

class IMSCognitiveDistractionDetector:
"""
基于EyeCue的IMS认知分心检测模块

部署优先级:P0(Euro NCAP 2027将要求)
"""

def __init__(self):
# 视觉编码器:选择轻量化模型
self.video_encoder = self.select_encoder()

# 眼动编码器:已有眼动追踪模块可复用
self.gaze_encoder = GazeEncoder()

# GDSQ模块:核心交互建模
self.gdsq = GazeDrivenSemanticQuery()

def select_encoder(self):
"""
编码器选择策略

高性能方案:
- TimeSformer-K600(论文最优)

边缘部署方案:
- MobileViT / EfficientViT
- 时序维度降采样
"""
if DEPLOYMENT_TARGET == 'edge':
return MobileVideoEncoder() # 轻量化
else:
return TimesformerModel.from_pretrained('timesformer-k600')

def inference_pipeline(self):
"""
推理流程

输入:
- 第一人称摄像头(RGB-IR)
- 眼动追踪坐标(已有DMS模块)

输出:
- 认知状态:专注/分心
- 置信度:0-1
- 分心时长:秒
"""
pass


# 功能优先级
feature_priority = {
"视觉分心检测": "P0 - 已实现",
"手动分心检测": "P0 - 已实现",
"疲劳检测(PERCLOS)": "P0 - 已实现",
"认知分心检测": "P1 - Euro NCAP 2027要求,建议优先开发"
}

2. 硬件配置建议

组件 推荐型号 参数 备注
RGB-IR摄像头 OV2311 2MP, 全局快门 已有DMS摄像头
眼动追踪 现有DMS模块 - 复用眼动数据
处理器 QCS8255 Hexagon NPU, 26 TOPS 已有平台
额外硬件 无需 - 软件升级即可

3. 开发路线图


graph LR
    A[数据收集] --> B[模型训练]
    B --> C[边缘部署]
    C --> D[功能验证]
    D --> E[法规认证]
    
    A -->|3个月| B
    B -->|2个月| C
    C -->|1个月| D
    D -->|2个月| E
    
    E --> F[Euro NCAP 2027合规]

时间估算:

  • 数据收集:3个月(标注CogDrive风格数据集)
  • 模型训练:2个月(在现有DMS平台基础上)
  • 边缘部署:1个月(量化+优化)
  • 功能验证:2个月(测试场景验证)
  • 法规认证:2个月(Euro NCAP合规测试)

总计:约10个月

4. 技术难点与解决方案

难点 挑战 解决方案
眼动质量依赖 眼动追踪误差影响检测 多帧平滑 + 鲁棒性训练
场景泛化 不同道路/天气场景 CogDrive多场景数据增强
实时性要求 ≤100ms推理延迟 模型量化 + NPU加速
误报控制 合理操作被误判为分心 场景上下文建模(如等红灯)

总结

EyeCue的核心贡献:

  1. 首次提出眼动-视频融合的认知分心检测框架
  2. GDSQ模块创新:眼动驱动语义查询,建模注视-上下文交互
  3. CogDrive数据集:3,662样本跨场景标注,填补领域空白
  4. 74.38%准确率,超越11个基线模型7%+

对IMS开发的意义:

维度 价值
法规合规 满足Euro NCAP 2027认知分心检测要求
技术先进 首个非侵入式认知分心检测方案
部署可行 无需额外硬件,软件升级即可
性能领先 超越现有方案7%+

下一步行动:

  1. 下载CogDrive数据集,验证模型性能
  2. 基于现有DMS平台,集成EyeCue模块
  3. 开展认知分心数据收集与标注
  4. 准备Euro NCAP 2027合规测试

参考文献

  1. Zhang, L., et al. “EyeCue: Driver Cognitive Distraction Detection via Gaze-Empowered Egocentric Video Understanding.” IJCAI 2026.
  2. Euro NCAP 2026 Assessment Protocol - DSM/OMS Requirements.
  3. Palazzi, A., et al. “DR(eye)VE: A Dataset for Attention-Aware Driving.” CVPR 2018.
  4. Kashevnik, A., et al. “Driver Distraction Detection Methods: A Review.” IEEE Trans. Intell. Transp. Syst. 2021.

下载资源:


EyeCue论文解读:基于眼动-视频融合的认知分心检测
https://dapalm.com/2026/06/04/2026-06-04-eyecue-cognitive-distraction-detection/
作者
Mars
发布于
2026年6月4日
许可协议