EyeCue:眼动+自我中心视频融合的认知分心检测框架

论文信息

核心创新

首次将时间序列眼动数据与自我中心视频融合,实现非侵入式认知分心检测。 EyeCue提出”眼动-上下文交互”建模思路,解决了认知分心难以检测的难题。

背景:认知分心检测的难点

驾驶分心分为三类:

类型 定义 检测难度 现有方案
手动分心 手离开方向盘(如拿手机) 摄像头检测肢体动作
视觉分心 视线偏离道路(如看导航) 摄像头检测视线方向
认知分心 思维游离,视线仍在道路 EEG/问卷(侵入式)

认知分心最难检测:驾驶员眼睛看着道路,但脑子在想别的事情。传统方法需要戴EEG头环或做检测响应任务,干扰正常驾驶。

核心洞察

研究发现在正常驾驶与认知分心时,眼动模式有显著差异:

  • 正常驾驶: 注视点广泛分布在环境中(红绿灯、行人、路牌)
  • 认知分心: 注视点集中在特定区域,与驾驶任务无关
graph LR
    A[驾驶员眼动数据] --> B{注视点分布}
    B -->|广泛分布| C[正常驾驶]
    B -->|集中固定| D[认知分心]
    
    E[自我中心视频] --> F[视觉上下文]
    F --> G[理解注视对象]
    
    A + E --> H[EyeCue模型]
    H --> I[分心状态判断]

EyeCue架构

三大模块

flowchart TB
    subgraph 输入
        V[自我中心视频]
        G[眼动坐标序列]
    end
    
    subgraph VideoEncoder[视频编码器]
        V --> V1[基于眼动的视频预处理]
        V1 --> V2[TimeSformer/VideoMAE]
        V2 --> V_CLS[v_CLS 全局特征]
        V2 --> P[patch tokens 细粒度特征]
    end
    
    subgraph GazeEncoder[眼动编码器]
        G --> G1[坐标嵌入]
        G1 --> G2[Transformer]
        G2 --> G_CLS[g_CLS 全局注视模式]
        G2 --> G_T[g_t 帧级注视特征]
    end
    
    subgraph GDSQ[眼动驱动语义查询]
        P --> S[注视区域patch选择]
        G_T --> Q[Query]
        S --> K[Key/Value]
        Q --> CA[交叉注意力]
        CA --> S_CLS[s_CLS 交互特征]
    end
    
    V_CLS --> F[特征拼接]
    G_CLS --> F
    S_CLS --> F
    
    F --> MLP[MLP分类器]
    MLP --> Y[分心/正常]

1. 视频编码器(Video Encoder)

  • 输入:自我中心驾驶视频(第一人称视角)
  • 预处理:基于眼动的三种策略
    • 点叠加(Dot Overlay):在注视点画绿点
    • 热力图掩码(Heatmap Mask):显示注视分布
    • 裁剪帧(Cropped Frame):聚焦注视区域
  • 骨干网络:TimeSformer-K600 或 VideoMAE-K400
  • 输出:
    • v_CLS:全局场景表示
    • patch tokens:细粒度视觉特征

2. 眼动编码器(Gaze Encoder)

  • 输入:眼动坐标序列 C = {(x_t, y_t)}_{t=1}^n
  • 处理:
    • 坐标投影到与视频patch相同嵌入空间
    • 添加可学习的类别token
    • 轻量级Transformer编码器(8头注意力,1层)
  • 输出:
    • g_CLS:全局注视模式
    • g_t:帧级注视特征

3. 眼动驱动语义查询(GDSQ)

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

算法流程:

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
# 算法:眼动驱动语义查询

def GDSQ(patch_tokens, gaze_features, gaze_coords):
"""
眼动驱动语义查询模块

Args:
patch_tokens: [n_frames, n_patches, dim] 视频patch特征
gaze_features: [n_frames, dim] 帧级眼动特征
gaze_coords: [n_frames, 2] 注视坐标

Returns:
s_CLS: 语义交互token
"""
S = [] # 注视区域patch tokens

for t in range(n_frames):
# 1. 根据注视坐标选择h个patch
patches = select_patches_around_gaze(
patch_tokens[t],
gaze_coords[t],
h=1 # 或h>1选择周围区域
)
S.append(patches)

# 2. 交叉注意力:眼动作为Query,patch作为Key/Value
# 直觉:驾驶员用眼动"查询"环境
for m in range(M): # M=2层
attention_output = cross_attention(
query=gaze_features,
key=S,
value=S
)
gaze_features = attention_output

# 3. 池化得到语义token
s_CLS = pooling(attention_output)

return s_CLS

直觉解释:

  • 眼动特征作为Query:驾驶员用眼睛”问”环境是什么
  • 注视区域patch作为Key/Value:环境”回答”驾驶员看到什么
  • 通过交叉注意力建模这种”问-答”交互

分类

拼接三个token:[v_CLS, g_CLS, s_CLS] → MLP → 分心/正常

CogDrive数据集

数据集构建

为解决数据集不足问题,作者整合四个现有数据集:

数据集 场景 注视数据 视频
DR(eye)VE 高速/城市
BDD-A 多样化
DADA-2000 事故场景
TrafficGaze 交通场景

标注协议(参照DR(eye)VE):

  • 定义”正常”与”分心”标准:基于注视-上下文交互
  • 两位标注员独立标注 + 领域专家审核
  • 标注员一致性 >98%

数据集统计

指标 数值
总片段数 3,662
正常片段 2,853
分心片段 809
剪辑长度 16帧

场景分布

CogDrive覆盖多样化场景:

  • 道路类型: 高速、城市、乡村
  • 时间段: 白天、黄昏、夜晚
  • 天气: 晴天、雨天、雾天

实验结果

主实验:超越所有基线

方法 准确率 F1分数
EyeCue (TimeSformer) 74.38% 0.72
EyeCue (VideoMAE) 72.15% 0.70
Gaze-only SVM 58.3% 0.55
TimeSformer (仅视频) 65.2% 0.62
EgoVideo 66.8% 0.64
InternVideo2 67.5% 0.65
Video-LLaVA 63.4% 0.60
GazeGPT 61.2% 0.58
GazeLLM 59.8% 0.56

结论: EyeCue比最强基线(InternVideo2)提升7%,证明眼动-上下文交互建模的有效性。

跨数据集泛化

采用留一数据集评估(Leave-One-Dataset-Out):

测试集 训练集 准确率
BDD-A DR(eye)VE + DADA-2000 + TrafficGaze 71.2%
DADA-2000 DR(eye)VE + BDD-A + TrafficGaze 70.8%
DR(eye)VE BDD-A + DADA-2000 + TrafficGaze 73.5%

结论: 在未见过的数据集上仍能保持>70%准确率,证明强泛化能力。

各模块贡献

配置 准确率
仅视频编码器 65.2%
+ 眼动编码器 69.5%
+ GDSQ 74.38%

结论: GDSQ模块贡献最大(+4.88%),证明眼动-上下文交互建模的关键作用。

视频预处理策略对比

预处理方式 准确率
无预处理 71.2%
点叠加 72.5%
热力图掩码 73.1%
裁剪帧 74.38%

结论: 裁剪帧策略最优,聚焦注视区域减少无关噪声。

代码复现

环境配置

1
2
3
4
5
6
7
# 克隆仓库
git clone https://github.com/langzhang2000/EyeCue.git
cd EyeCue

# 安装依赖
pip install torch torchvision transformers
pip install timm einops

模型实现

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
import torch
import torch.nn as nn
from transformers import TimeSformerModel

class EyeCue(nn.Module):
"""
EyeCue: 眼动赋能的自我中心视频认知分心检测

核心组件:
1. 视频编码器:提取全局场景和细粒度特征
2. 眼动编码器:建模时间注视模式
3. GDSQ:眼动-上下文交互建模
"""

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

# 视频编码器
self.video_encoder = TimeSformerModel.from_pretrained(
'facebook/timesformer-base-224-k600'
)

# 眼动编码器
self.gaze_encoder = GazeEncoder(
d_model=768,
n_heads=8,
n_layers=1
)

# GDSQ模块
self.gdsq = GazeDrivenSemanticQuery(
d_model=768,
n_heads=8,
n_layers=2
)

# 分类器
self.classifier = nn.Sequential(
nn.Linear(768 * 3, 512),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(512, 2)
)

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

Args:
video: [B, T, C, H, W] 自我中心视频
gaze_coords: [B, T, 2] 注视坐标序列

Returns:
logits: [B, 2] 分心/正常分类
"""
B, T = video.shape[:2]

# 1. 视频编码
video_output = self.video_encoder(video)
v_cls = video_output.last_hidden_state[:, 0] # [B, 768]
patch_tokens = video_output.last_hidden_state[:, 1:] # [B, T*patch_num, 768]

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

# 3. GDSQ:眼动-上下文交互
s_cls = self.gdsq(patch_tokens, gaze_features, gaze_coords) # [B, 768]

# 4. 分类
fused = torch.cat([v_cls, g_cls, s_cls], dim=-1) # [B, 768*3]
logits = self.classifier(fused) # [B, 2]

return logits


class GazeEncoder(nn.Module):
"""眼动编码器"""

def __init__(self, d_model, n_heads, n_layers):
super().__init__()

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

# Transformer
encoder_layer = nn.TransformerEncoderLayer(
d_model=d_model,
nhead=n_heads,
batch_first=True
)
self.transformer = nn.TransformerEncoder(encoder_layer, num_layers=n_layers)

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

def forward(self, gaze_coords):
"""
Args:
gaze_coords: [B, T, 2]

Returns:
g_cls: [B, d_model] 全局注视模式
gaze_features: [B, T, d_model] 帧级注视特征
"""
B, T = gaze_coords.shape[:2]

# 坐标嵌入
gaze_embed = self.coord_embed(gaze_coords) # [B, T, d_model]

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

# Transformer编码
x = self.transformer(x) # [B, T+1, d_model]

g_cls = x[:, 0] # [B, d_model]
gaze_features = x[:, 1:] # [B, T, d_model]

return g_cls, gaze_features


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

def __init__(self, d_model, n_heads, n_layers):
super().__init__()

self.n_layers = n_layers

# 多层交叉注意力
self.cross_attn_layers = nn.ModuleList([
nn.MultiheadAttention(d_model, n_heads, batch_first=True)
for _ in range(n_layers)
])

self.norm = nn.LayerNorm(d_model)

def forward(self, patch_tokens, gaze_features, gaze_coords):
"""
Args:
patch_tokens: [B, N, d_model] 视频patch tokens
gaze_features: [B, T, d_model] 帧级眼动特征
gaze_coords: [B, T, 2] 注视坐标

Returns:
s_cls: [B, d_model] 语义交互token
"""
B, T = gaze_coords.shape[:2]

# 1. 根据注视坐标选择patch
selected_patches = self.select_patches_by_gaze(
patch_tokens, gaze_coords, h=1
) # [B, T, d_model]

# 2. 多层交叉注意力
query = gaze_features # 眼动作为Query
kv = selected_patches # patch作为Key/Value

for cross_attn in self.cross_attn_layers:
attn_output, _ = cross_attn(query, kv, kv)
query = self.norm(query + attn_output)

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

return s_cls

def select_patches_by_gaze(self, patch_tokens, gaze_coords, h=1):
"""
根据注视坐标选择patch tokens

Args:
patch_tokens: [B, N, d_model]
gaze_coords: [B, T, 2] 坐标范围[0, 1]
h: 选择patch数量

Returns:
selected: [B, T, d_model]
"""
B, N, d = patch_tokens.shape
T = gaze_coords.shape[1]

# 将坐标转换为patch索引(假设patch_num = N//T)
patches_per_frame = N // T

selected = []
for t in range(T):
# 计算注视点对应的patch索引
gx, gy = gaze_coords[:, t, 0], gaze_coords[:, t, 1]
patch_idx = (gx * patches_per_frame).long() % patches_per_frame

# 选择对应patch
start_idx = t * patches_per_frame
selected_patch = patch_tokens[:, start_idx + patch_idx] # [B, d]
selected.append(selected_patch)

return torch.stack(selected, dim=1) # [B, T, d]


# 推理示例
if __name__ == "__main__":
# 模型配置
config = {
'd_model': 768,
'n_heads': 8,
'n_layers': 1,
'n_gdsq_layers': 2
}

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

# 模拟输入
B, T, C, H, W = 1, 16, 3, 224, 224
video = torch.randn(B, T, C, H, W)
gaze_coords = torch.rand(B, T, 2) # 坐标范围[0, 1]

# 推理
with torch.no_grad():
logits = model(video, gaze_coords)
probs = torch.softmax(logits, dim=-1)

print(f"分心概率: {probs[0, 1].item():.2%}")
print(f"正常概率: {probs[0, 0].item():.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
# 完整推理流程

def inference_pipeline(video_path, gaze_data):
"""
认知分心检测推理流程

Args:
video_path: 自我中心视频文件路径
gaze_data: 眼动追踪数据(时间戳 + 坐标)

Returns:
distraction_score: 分心分数 [0, 1]
"""
# 1. 视频预处理
frames = load_video(video_path, fps=30) # [T, H, W, C]

# 2. 眼动预处理
gaze_coords = preprocess_gaze(gaze_data, len(frames)) # [T, 2]

# 3. 基于注视点裁剪帧
cropped_frames = crop_frames_by_gaze(frames, gaze_coords)

# 4. 模型推理
video_tensor = torch.tensor(cropped_frames).unsqueeze(0) # [1, T, C, H, W]
gaze_tensor = torch.tensor(gaze_coords).unsqueeze(0) # [1, T, 2]

with torch.no_grad():
logits = model(video_tensor, gaze_tensor)
probs = torch.softmax(logits, dim=-1)

distraction_score = probs[0, 1].item()

return distraction_score

IMS应用启示

1. 系统架构设计

flowchart TB
    subgraph 数据采集
        AR[AR眼镜/车载摄像头]
        ET[眼动追踪模块]
    end
    
    subgraph 预处理
        VF[视频帧提取]
        GP[注视点坐标]
        GC[基于注视裁剪]
    end
    
    subgraph 模型推理
        VE[视频编码器]
        GE[眼动编码器]
        GDSQ[GDSQ模块]
    end
    
    subgraph 输出
        SCORE[分心分数]
        ALERT[警报触发]
    end
    
    AR --> VF
    ET --> GP
    VF --> GC
    GP --> GC
    
    GC --> VE
    GP --> GE
    VE --> GDSQ
    GE --> GDSQ
    
    VE --> FUSION[特征融合]
    GE --> FUSION
    GDSQ --> FUSION
    
    FUSION --> SCORE
    SCORE --> ALERT
    
    style ALERT fill:#ff6b6b

2. 硬件需求

组件 规格 作用
AR眼镜 Meta Aria Gen 2 / HoloLens 自我中心视频采集
眼动追踪 Tobii Eye Tracker / 内置 注视点坐标
计算单元 Snapdragon Ride / Orin-X 模型推理
内存 ≥8GB 视频缓冲

3. 实时性优化

模型压缩:

  • TimeSformer → 蒸馏到轻量级模型
  • INT8量化减少内存占用

流水线优化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 异步流水线
async def real_time_detection():
while True:
# 1. 异步获取帧
frame = await get_frame_async()
gaze = await get_gaze_async()

# 2. 批量推理
if buffer_ready():
results = model.infer_batch(buffer)
buffer.clear()

# 3. 结果处理
if results['distraction'] > 0.7:
trigger_alert()

4. Euro NCAP 2026合规

要求 EyeCue方案 合规性
非侵入式 仅需AR眼镜/摄像头 ✅ 符合
实时检测 30fps推理速度 ✅ 符合
多场景泛化 CogDrive验证 ✅ 符合
分心检测 准确率74.38% 🟡 待提升

5. 局限与改进方向

局限:

  1. AR眼镜普及率低,依赖特殊硬件
  2. 准确率74%仍有提升空间
  3. 未考虑疲劳叠加效应

改进方向:

  1. 无眼镜方案: 用中控摄像头替代AR眼镜,重建驾驶员视角
  2. 多模态融合: 加入方向盘扭矩、车速等车辆信号
  3. 时序建模增强: 使用Transformer-XL建模长时依赖
  4. 主动学习: 在线适应个体驾驶员习惯

6. 部署路线图

gantt
    title EyeCue IMS集成路线图
    dateFormat  YYYY-MM-DD
    section 原型验证
    数据采集系统搭建       :a1, 2026-01-01, 30d
    模型离线验证           :a2, after a1, 20d
    section 系统集成
    嵌入式部署优化         :b1, after a2, 30d
    实时推理流水线         :b2, after b1, 20d
    section 验证测试
    实车数据采集           :c1, after b2, 30d
    Euro NCAP场景测试      :c2, after c1, 20d
    section 量产准备
    功能安全认证           :d1, after c2, 30d
    SOP准备                :d2, after d1, 20d

总结

EyeCue首次实现非侵入式认知分心检测,通过眼动-上下文交互建模突破传统方法局限。74.38%的准确率证明方法有效性,为Euro NCAP 2026认知分心检测要求提供可行方案。

关键要点:

  1. 认知分心可用眼动模式识别(注视点集中 vs 广泛分布)
  2. 眼动-视频融合优于单模态方法
  3. GDSQ模块是性能提升的关键
  4. 需配合AR眼镜或第一人称摄像头部署

IMS开发优先级:高


EyeCue:眼动+自我中心视频融合的认知分心检测框架
https://dapalm.com/2026/07/17/2026-07-17-01-EyeCue-Cognitive-Distraction-Gaze-Egocentric/
作者
Mars
发布于
2026年7月17日
许可协议