Toyota IDD:首个酒驾+认知分心+道路危险三合一驾驶损伤数据集

论文信息

项目 内容
论文标题 A Simulator Dataset to Support the Study of Impaired Driving
作者 John Gideon, Kimimasa Tamura, Emily Sumner, Laporsha Dees, Patricio Reyes Gomez, Bassamul Haq, Todd Rowell, Avinash Balachandran, Simon Stent, Guy Rosman
机构 Toyota Research Institute (TRI), USA
会议 IEEE ITSC 2025 (28th International Conference on Intelligent Transportation Systems)
页码 831-838
数据集 https://toyotaresearchinstitute.github.io/IDD/
arXiv 2507.02867

核心创新

Toyota Research Institute 发布了首个同时包含酒精损伤、认知分心和道路危险的驾驶模拟器数据集(Impaired Driving Dataset, IDD)。

与现有数据集对比

数据集 酒精 认知分心 道路危险 视线追踪 车辆控制 场景真值 受试者 时长(h)
C42CN ❌ ✅ ✅* ✅ ✅ ❌ 68 80
CoCAtt ❌ ✅ ❌ ✅ ✅ ❌ 11 12
Koch et al. ✅ ❌ ❌ ✅ ✅ ❌ 30 15
Keshtkaran ✅ ❌ ❌ ✅† ❌ ❌ 60 30
CL-Drive ❌ ✅‡ ❌ ✅ ❌ ❌ 21 10
IDD (Ours) ✅ ✅ ✅ ✅ ✅ ✅ 52 25

*One hazard scenario involving unintended acceleration. †Gaze derived from RGB video. ‡Cognitive workload measured as dependent variable.

方法详解

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
"""
Toyota IDD 实验设计复现
52名受试者, 2组, 2条件, 8个道路危险事件

依赖: 无 (数据集分析脚本)
数据集: https://toyotaresearchinstitute.github.io/IDD/
"""

import numpy as np
import pandas as pd
from dataclasses import dataclass
from typing import List, Dict, Tuple

@dataclass
class ImpairedDrivingExperiment:
"""
Toyota IDD 实验协议

2×2 析因设计:
- 酒精因素: BAC 0.00% vs BAC 0.10%
- 认知因素: 正常驾驶 vs 认知分心
"""

# 受试者分组
intoxicated_group_size: int = 20 # BAC ≥ 0.10%
sober_group_size: int = 32 # BAC = 0.00%
total_subjects: int = 52

# 驾驶条件
conditions: List[str] = None

# 道路危险事件 (8个)
hazards: List[str] = None

# 数据采集频率
eye_tracking_hz: int = 60 # Tobii Pro Spectrum
vehicle_telemetry_hz: int = 100
rgb_video_fps: int = 30

def __post_init__(self):
self.conditions = [
"normal_driving", # 正常驾驶
"cognitive_distraction_1back", # 音频1-back任务
"cognitive_distraction_sentence", # 句子理解任务
]
self.hazards = [
"pedestrian_crossing", # 行人突然横穿
"vehicle_cut_in", # 车辆加塞
"red_light_violation", # 红灯闯入
"emergency_brake", # 紧急制动
"lane_departure", # 车道偏离
"intersection_conflict", # 路口冲突
"merge_conflict", # 并线冲突
"object_in_road" # 路面障碍物
]

def get_data_streams(self) -> Dict[str, str]:
"""返回数据集包含的所有数据流"""
return {
# 车辆与场景数据
"vehicle_controls": "steering, throttle, braking, speed",
"scene_rgb": "ground truth RGB camera",
"scene_depth": "ground truth depth map",
"scene_semantic": "ground truth semantic segmentation",

# 驾驶员数据
"gaze_vector": "60Hz eye tracking, gaze vectors",
"gaze_fixations": "fixation points and durations",
"gaze_saccades": "saccade events",
"pupil_diameter": "pupil size (mm)",
"audio": "in-cabin audio",

# 主观评估
"panas": "Positive and Negative Affect Schedule",
"nasa_tlx": "NASA Task Load Index",
"kss": "Karolinska Sleepiness Scale",
}

def get_dataset_stats(self) -> Dict[str, float]:
"""数据集统计"""
return {
"total_hours": 23.7,
"total_km": 839,
"hazard_encounters": 395,
"collision_rate_sober": 0.29, # 每次出行碰撞率
"collision_rate_intoxicated": 0.65, # 翻倍!
"hazard_crash_rate_sober": 0.06,
"hazard_crash_rate_intoxicated": 0.13,
}


# ========== 数据分析 ==========
if __name__ == "__main__":
exp = ImpairedDrivingExperiment()

print("=" * 60)
print("Toyota IDD 数据集概览")
print("=" * 60)

print(f"\n受试者: {exp.total_subjects}人")
print(f" - 酒精组: {exp.intoxicated_group_size}人 (BAC ≥ 0.10%)")
print(f" - 清醒组: {exp.sober_group_size}人 (BAC = 0.00%)")

print(f"\n道路危险事件: {len(exp.hazards)}种")
for i, h in enumerate(exp.hazards):
print(f" {i+1}. {h}")

print(f"\n数据流:")
for k, v in exp.get_data_streams().items():
print(f" {k}: {v}")

stats = exp.get_dataset_stats()
print(f"\n关键统计:")
print(f" 总时长: {stats['total_hours']}h")
print(f" 总里程: {stats['total_km']}km")
print(f" 危险事件: {stats['hazard_encounters']}次")
print(f" 碰撞率: 清醒{stats['collision_rate_sober']:.2f} → 酒驾{stats['collision_rate_intoxicated']:.2f} (×{stats['collision_rate_intoxicated']/stats['collision_rate_sober']:.1f})")

2. 关键发现:酒精与认知分心的交互效应

发现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
import numpy as np
import matplotlib.pyplot as plt

def analyze_gaze_narrowing(gaze_data, condition_labels):
"""
分析不同条件下的视线分布

论文发现:酒精和认知分心都导致"隧道视觉"
- 凝视点减少 (fewer fixations)
- 扫视减少 (fewer saccades)
- 视线集中于前方路面
- 忽略周边信息
"""
fig, axes = plt.subplots(1, 3, figsize=(15, 5))

conditions = ['正常驾驶', '认知分心', '酒精损伤']
colors = ['green', 'orange', 'red']

for i, (cond, color) in enumerate(zip(conditions, colors)):
# 模拟视线分布数据 (基于论文描述)
if cond == '正常驾驶':
x, y = np.random.multivariate_normal(
[0.5, 0.3], [[0.08, 0], [0, 0.05]], 500
).T
elif cond == '认知分心':
x, y = np.random.multivariate_normal(
[0.5, 0.25], [[0.03, 0], [0, 0.02]], 500
).T # 更窄的分布
else: # 酒精
x, y = np.random.multivariate_normal(
[0.5, 0.2], [[0.02, 0], [0, 0.015]], 500
).T # 最窄的分布

axes[i].scatter(x, y, alpha=0.3, s=10, c=color)
axes[i].set_xlim(0, 1)
axes[i].set_ylim(0, 1)
axes[i].set_title(f'{cond}\n视线分布', fontsize=12)
axes[i].set_xlabel('水平视线位置')
axes[i].set_ylabel('垂直视线位置')

plt.suptitle('Toyota IDD: 酒精与认知分心的"隧道视觉"效应', fontsize=14)
plt.tight_layout()
plt.savefig('gaze_tunnel_vision.png', dpi=150, bbox_inches='tight')
plt.show()

# 量化指标
print("\n视线分布统计:")
print(f"{'条件':<15} {'水平标准差':<12} {'垂直标准差':<12} {'凝视密度':<12}")
print("-" * 50)
for cond, x_data, y_data in [
('正常驾驶', x_normal, y_normal),
('认知分心', x_cog, y_cog),
('酒精损伤', x_alc, y_alc)
]:
print(f"{cond:<15} {np.std(x_data):<12.4f} {np.std(y_data):<12.4f} {len(np.unique(x_data)):<12}")

发现3:眼动特征是最强损伤指标

特征类型 酒精检测效果 认知分心检测效果 组合检测效果
视线分布熵 ✅ 优秀 ✅ 优秀 ✅ 优秀
扫视频率 ✅ 优秀 ✅ 良好 ⚠️ 中等
瞳孔直径 ⚠️ 中等 ✅ 良好 ✅ 优秀
方向盘微修正 ✅ 优秀 ❌ 无效 ⚠️ 中等
速度方差 ✅ 良好 ❌ 反向 ❌ 被抵消

3. 数据集结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
IDD/
├── subjects/
│ ├── subj_001/
│ │ ├── normal/
│ │ │ ├── vehicle_data.csv # 100Hz 车辆遥测
│ │ │ ├── gaze_data.csv # 60Hz 眼动追踪
│ │ │ ├── rgb_video.mp4 # 30fps 驾驶员视角
│ │ │ ├── scene_rgb/ # 场景RGB帧 (真值)
│ │ │ ├── scene_depth/ # 场景深度图 (真值)
│ │ │ ├── scene_semantic/ # 语义分割 (真值)
│ │ │ ├── audio.wav # 车内音频
│ │ │ └── surveys.json # PANAS, NASA-TLX, KSS
│ │ ├── cognitive_1back/
│ │ ├── cognitive_sentence/
│ │ └── ...
│ ├── subj_002/
│ └── ... (52 subjects)
├── hazard_events/
│ ├── pedestrian_crossing/
│ ├── vehicle_cut_in/
│ └── ... (8 hazard types)
├── metadata.json
└── README.md

IMS 开发启示

1. 算法开发路线

2. 直接可用的发现

IDD发现 IMS落地建议 优先级
速度被抵消 不要单独依赖车速做损伤检测 🔴 P0
方向盘微修正 加入方向盘信号做酒驾特征 🔴 P0
隧道视觉 计算视线分布熵,低熵=损伤 🔴 P0
瞳孔直径 需要IR摄像头支持瞳孔测量 🟡 P1
1-back任务 可作为校准阶段认知负荷基线 🟢 P2

3. 眼动特征提取代码

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
import numpy as np
from scipy.stats import entropy

def extract_gaze_features(gaze_x, gaze_y, fixations, saccades, pupil_diameter):
"""
从IDD数据集提取损伤检测关键特征

Args:
gaze_x: (N,) 水平视线位置 0-1
gaze_y: (N,) 垂直视线位置 0-1
fixations: list of (start, end, duration)
saccades: list of (start, end, amplitude)
pupil_diameter: (N,) 瞳孔直径 mm

Returns:
features: dict, 用于损伤分类的特征向量
"""
features = {}

# 1. 视线分布熵 (隧道视觉检测)
hist_2d, _, _ = np.histogram2d(gaze_x, gaze_y, bins=20)
hist_2d_norm = hist_2d / hist_2d.sum()
features['gaze_entropy'] = entropy(hist_2d_norm.flatten())

# 2. 凝视统计
fix_durations = [f[2] for f in fixations]
features['fixation_count'] = len(fixations)
features['mean_fixation_duration'] = np.mean(fix_durations)
features['fixation_rate'] = len(fixations) / (len(gaze_x) / 60) # 每秒凝视数

# 3. 扫视统计
saccade_amplitudes = [s[2] for s in saccades]
features['saccade_count'] = len(saccades)
features['mean_saccade_amplitude'] = np.mean(saccade_amplitudes) if saccade_amplitudes else 0

# 4. 瞳孔直径
features['pupil_mean'] = np.mean(pupil_diameter)
features['pupil_std'] = np.std(pupil_diameter)
features['pupil_trend'] = np.polyfit(range(len(pupil_diameter)),
pupil_diameter, 1)[0]

# 5. 视线覆盖范围 (隧道视觉量化)
features['gaze_x_std'] = np.std(gaze_x)
features['gaze_y_std'] = np.std(gaze_y)
features['gaze_spread'] = np.sqrt(
np.var(gaze_x) + np.var(gaze_y)
)

return features


# 损伤分类器 (基线)
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score

def train_impairment_classifier(features_dict, labels):
"""
使用IDD提取的特征训练损伤分类器

Args:
features_dict: list of feature dicts
labels: 0=正常, 1=认知分心, 2=酒精损伤, 3=复合

Returns:
clf: 训练好的分类器
"""
# 转换为特征矩阵
feature_names = list(features_dict[0].keys())
X = np.array([[f[k] for k in feature_names] for f in features_dict])
y = np.array(labels)

# 训练随机森林
clf = RandomForestClassifier(n_estimators=100, max_depth=10, random_state=42)

# 10折交叉验证
scores = cross_val_score(clf, X, y, cv=10, scoring='f1_macro')

print(f"损伤分类器性能:")
print(f" 特征数: {len(feature_names)}")
print(f" 10折交叉验证 F1: {scores.mean():.3f} ± {scores.std():.3f}")

clf.fit(X, y)

# 特征重要性
importances = sorted(zip(feature_names, clf.feature_importances_),
key=lambda x: -x[1])
print(f"\n特征重要性排序:")
for name, imp in importances:
print(f" {name}: {imp:.4f}")

return clf


if __name__ == "__main__":
# 模拟IDD数据提取
np.random.seed(42)

# 模拟正常驾驶眼动数据 (60Hz, 60秒)
n_samples = 60 * 60
normal_gaze_x = np.random.normal(0.5, 0.15, n_samples)
normal_gaze_y = np.random.normal(0.3, 0.12, n_samples)
normal_pupil = np.random.normal(4.0, 0.3, n_samples)

# 模拟认知分心 (隧道视觉)
cog_gaze_x = np.random.normal(0.5, 0.08, n_samples)
cog_gaze_y = np.random.normal(0.25, 0.06, n_samples)
cog_pupil = np.random.normal(4.2, 0.4, n_samples) # 瞳孔扩张

# 模拟酒精损伤 (更窄的隧道视觉)
alc_gaze_x = np.random.normal(0.5, 0.05, n_samples)
alc_gaze_y = np.random.normal(0.2, 0.04, n_samples)
alc_pupil = np.random.normal(3.8, 0.2, n_samples)

# 提取特征
print("正常驾驶特征:")
normal_feat = extract_gaze_features(
normal_gaze_x, normal_gaze_y,
[(0, 60, 0.3)] * 80, [(60, 65, 5)] * 40,
normal_pupil
)
for k, v in normal_feat.items():
print(f" {k}: {v:.4f}")

print("\n认知分心特征:")
cog_feat = extract_gaze_features(
cog_gaze_x, cog_gaze_y,
[(0, 60, 0.5)] * 50, [(60, 65, 3)] * 25,
cog_pupil
)
for k, v in cog_feat.items():
print(f" {k}: {v:.4f}")

print("\n酒精损伤特征:")
alc_feat = extract_gaze_features(
alc_gaze_x, alc_gaze_y,
[(0, 60, 0.7)] * 30, [(60, 65, 2)] * 15,
alc_pupil
)
for k, v in alc_feat.items():
print(f" {k}: {v:.4f}")

# 关键指标对比
print("\n" + "=" * 50)
print("隧道视觉量化 (gaze_spread):")
print(f" 正常: {normal_feat['gaze_spread']:.4f}")
print(f" 认知分心: {cog_feat['gaze_spread']:.4f} (×{cog_feat['gaze_spread']/normal_feat['gaze_spread']:.2f})")
print(f" 酒精损伤: {alc_feat['gaze_spread']:.4f} (×{alc_feat['gaze_spread']/normal_feat['gaze_spread']:.2f})")

4. 数据集获取

1
2
3
4
5
6
7
8
9
# 下载IDD数据集
git clone https://github.com/toyotaresearchinstitute/IDD.git
cd IDD

# 查看数据集说明
cat README.md

# 数据集大小约 50-100GB (包含视频+眼动+遥测)
# 建议按需下载特定subjects的数据

5. 与IMS集成的测试场景

测试场景 对应IDD条件 IMS检测目标 通过标准
IDM-01 正常驾驶基线 Sober + Normal 建立驾驶员基线 5分钟内无误报
IDM-02 认知分心 Sober + 1-back 检测认知分心 ≤10秒检测到
IDM-03 酒精损伤 Intoxicated + Normal 检测酒驾 ≤30秒检测到
IDM-04 复合损伤 Intoxicated + 1-back 检测复合状态 ≤30秒检测到
IDM-05 危险响应 Intoxicated + Hazard 检测+危险响应 碰撞率降低>50%

参考文献

  1. Gideon, J. et al. “A Simulator Dataset to Support the Study of Impaired Driving.” IEEE ITSC 2025, pp. 831-838. arXiv: 2507.02867.
  2. Dataset: https://toyotaresearchinstitute.github.io/IDD/
  3. CARLA Simulator: Dosovitskiy, A. et al. “CARLA: An Open Urban Driving Simulator.” arXiv: 1711.03938.

Toyota IDD 是目前唯一同时包含酒精损伤和认知分心的驾驶数据集,对于IMS开发酒驾+认知分心联合检测算法具有不可替代的价值。数据集已公开,建议立即下载用于算法训练。