NTHU-DDD数据集详解:疲劳检测基准数据集使用指南

NTHU-DDD数据集详解:疲劳检测基准数据集使用指南

数据集来源: NTHU Computer Vision Lab
状态: 公开数据集
用途: 疲劳检测算法基准测试


数据集信息

项目 内容
名称 NTHU Driver Drowsiness Dataset (NTHU-DDD)
机构 台湾清华大学计算机视觉实验室
规模 36个受试者
场景 5种(白天/夜晚/眼镜/墨镜/各种光照)
标注 疲劳等级(0-4)

数据集统计

受试者分布

类别 数量
总受试者 36人
男性 22人
女性 14人
戴眼镜 18人
戴墨镜 12人
不同种族 亚洲、欧洲、非洲

场景配置

场景 光照条件 配件 视频数
场景1 白天 36
场景2 夜晚 36
场景3 白天 眼镜 36
场景4 白天 墨镜 36
场景5 混合 混合 36

疲劳等级标注

五级标注标准

等级 状态 眼睑开度 PERCLOS 标注特征
0 清醒 >80% <10% 眼睛完全睁开,目光专注
1 轻微疲劳 60-80% 10-20% 眼睑略微下垂,眨眼略频繁
2 中度疲劳 40-60% 20-30% 眼睑明显下垂,偶有打哈欠
3 重度疲劳 20-40% 30-50% 眼睛半闭,频繁打哈欠
4 极度疲劳 <20% >50% 眼睛完全闭合,微睡眠

标注流程

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
import numpy as np
from typing import Dict

class NTHUDDDAnnotation:
"""
NTHU-DDD数据集标注格式

每帧标注:
- fatigue_level: 0-4
- eye_state: "open", "half-close", "close"
- yawning: bool
- head_pose: (pitch, yaw, roll)
"""

def __init__(self, annotation_file: str):
self.annotations = self._load_annotations(annotation_file)

def _load_annotations(self, file_path: str) -> Dict:
"""加载标注文件"""
# 简化:返回示例格式
return {
"frame_id": [0, 1, 2],
"fatigue_level": [0, 1, 2],
"eye_state": ["open", "half-close", "close"],
"yawning": [False, False, True],
"head_pose": [(0, 0, 0), (5, 10, 0), (10, 20, 5)]
}

def get_fatigue_distribution(self) -> Dict:
"""获取疲劳等级分布"""
levels = self.annotations["fatigue_level"]

distribution = {
0: levels.count(0),
1: levels.count(1),
2: levels.count(2),
3: levels.count(3),
4: levels.count(4)
}

return distribution

def compute_statistics(self) -> Dict:
"""计算数据集统计信息"""
levels = np.array(self.annotations["fatigue_level"])

return {
"total_frames": len(levels),
"normal_frames": np.sum(levels == 0),
"fatigue_frames": np.sum(levels > 0),
"severe_fatigue_frames": np.sum(levels >= 3),
"avg_fatigue_level": np.mean(levels),
"std_fatigue_level": np.std(levels)
}


# 示例使用
if __name__ == "__main__":
annotation = NTHUDDDAnnotation("dummy_path")

distribution = annotation.get_fatigue_distribution()
print("疲劳等级分布:", distribution)

stats = annotation.compute_statistics()
for key, value in stats.items():
print(f"{key}: {value}")

数据加载与预处理

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
import cv2
import numpy as np
from pathlib import Path

class NTHUDDDLoader:
"""
NTHU-DDD数据集加载器

支持功能:
- 视频帧提取
- 人脸检测与对齐
- 数据增强
"""

def __init__(self,
data_root: str,
target_size: tuple = (224, 224)):
self.data_root = Path(data_root)
self.target_size = target_size

# 人脸检测器
self.face_detector = cv2.CascadeClassifier(
cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'
)

def load_video(self,
video_path: str,
max_frames: int = 1000) -> np.ndarray:
"""
加载视频

Args:
video_path: 视频文件路径
max_frames: 最大帧数

Returns:
frames: 视频帧数组, shape=(N, H, W, C)
"""
cap = cv2.VideoCapture(video_path)

frames = []
while len(frames) < max_frames:
ret, frame = cap.read()
if not ret:
break

frames.append(frame)

cap.release()

return np.array(frames)

def detect_face(self,
frame: np.ndarray) -> np.ndarray:
"""
人脸检测与裁剪

Args:
frame: 输入图像

Returns:
face: 裁剪后的人脸图像
"""
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

faces = self.face_detector.detectMultiScale(
gray, scaleFactor=1.1, minNeighbors=5
)

if len(faces) == 0:
return cv2.resize(frame, self.target_size)

# 取最大人脸
x, y, w, h = max(faces, key=lambda f: f[2] * f[3])

# 扩展边界
margin = 0.2
x = max(0, int(x - w * margin))
y = max(0, int(y - h * margin))
w = min(frame.shape[1] - x, int(w * (1 + 2 * margin)))
h = min(frame.shape[0] - y, int(h * (1 + 2 * margin)))

face = frame[y:y+h, x:x+w]

# 调整大小
face = cv2.resize(face, self.target_size)

return face

def augment_frame(self,
frame: np.ndarray,
augment_type: str = "random") -> np.ndarray:
"""
数据增强

Args:
frame: 输入帧
augment_type: 增强类型

Returns:
augmented_frame: 增强后的帧
"""
if augment_type == "random":
augment_type = np.random.choice([
"brightness", "contrast", "blur", "noise", "flip"
])

if augment_type == "brightness":
# 亮度调整
factor = np.random.uniform(0.7, 1.3)
frame = cv2.convertScaleAbs(frame, alpha=factor, beta=0)

elif augment_type == "contrast":
# 对比度调整
factor = np.random.uniform(0.7, 1.3)
mean = frame.mean()
frame = cv2.convertScaleAbs(frame, alpha=factor, beta=mean * (1 - factor))

elif augment_type == "blur":
# 高斯模糊
kernel_size = np.random.choice([3, 5, 7])
frame = cv2.GaussianBlur(frame, (kernel_size, kernel_size), 0)

elif augment_type == "noise":
# 添加噪声
noise = np.random.randn(*frame.shape) * 10
frame = np.clip(frame + noise, 0, 255).astype(np.uint8)

elif augment_type == "flip":
# 水平翻转
frame = cv2.flip(frame, 1)

return frame

def create_dataloader(self,
batch_size: int = 32,
shuffle: bool = True):
"""
创建PyTorch数据加载器

Args:
batch_size: 批次大小
shuffle: 是否打乱

Returns:
dataloader: PyTorch DataLoader
"""
import torch
from torch.utils.data import Dataset, DataLoader

class NTHUDDDataset(Dataset):
def __init__(self, loader):
self.loader = loader

def __len__(self):
return 100 # 简化

def __getitem__(self, idx):
frame = np.random.randint(0, 255, (224, 224, 3), dtype=np.uint8)
label = np.random.randint(0, 5)

return torch.from_numpy(frame).permute(2, 0, 1).float(), label

dataset = NTHUDDDataset(self)

return DataLoader(
dataset,
batch_size=batch_size,
shuffle=shuffle
)


# 示例使用
if __name__ == "__main__":
loader = NTHUDDDLoader(data_root="/path/to/nthu-ddd")

# 创建数据加载器
dataloader = loader.create_dataloader(batch_size=16)

print(f"数据加载器创建完成")
print(f"批次数: {len(dataloader)}")

# 测试一批数据
for frames, labels in dataloader:
print(f"批次帧形状: {frames.shape}")
print(f"批次标签: {labels}")
break

Euro NCAP基准对齐

Euro NCAP场景 NTHU-DDD对应标注 评估指标
F-01 PERCLOS 眼睑开度计算 PERCLOS误差 < 5%
F-02 闭眼检测 eye_state标注 闭眼检出率 > 95%
F-03 打哈欠 yawning标注 打哈欠检出率 > 90%
F-04 微睡眠 fatigue_level=4 微睡眠检出率 > 90%
F-05 头部下垂 head_pose标注 姿态估计误差 < 10°

参考资料

  1. NTHU-DDD Dataset
  2. EmergentMind: NTHU-DDD
  3. Euro NCAP 2026 Fatigue Scenarios

总结

NTHU-DDD数据集特点:

  1. 规模适中:36人,5场景
  2. 标注详细:5级疲劳、眼态、哈欠、头姿
  3. 多场景覆盖:白天/夜晚/眼镜/墨镜
  4. 公开可获取:学术研究免费

使用建议:

  • 🔴 训练集:60%(22人)
  • 🟡 验证集:20%(7人)
  • 🟢 测试集:20%(7人)

下一步行动:

  • 下载NTHU-DDD数据集
  • 实现数据加载器
  • 对齐Euro NCAP F-01至F-05评估指标

NTHU-DDD数据集详解:疲劳检测基准数据集使用指南
https://dapalm.com/2026/07/09/2026-07-09-nthu-ddd-dataset-fatigue-benchmark-guide/
作者
Mars
发布于
2026年7月9日
许可协议