Transformer 架构疲劳检测:从 92% 到 99.15% 的性能跃升

发布日期: 2026-04-13
标签: Transformer, ViT, Swin Transformer, 疲劳检测, PERCLOS, 深度学习
来源: Nature Scientific Reports 2025、PMC、行业研究


核心发现:Transformer 超越 CNN

Nature Scientific Reports 2025 年发表的研究表明:

模型类型 代表模型 准确率 关键优势
传统启发式 PERCLOS、EAR 72-90% 无需训练,但依赖阈值
CNN 系列 VGG19、ResNet 92-97% 局部特征强,全局弱
Transformer ViT、Swin 99.15% 全局注意力,长距依赖

准确率演进

1
2
3
4
5
6
PERCLOS (传统)    EAR (传统)     CNN (VGG16)    CNN (VGG19)    Transformer (ViT)
72% → 90% → 92-97% → 98.7% → 99.15%

↓ ↓ ↓ ↓ ↓
依赖阈值 眼部几何 局部特征 更深网络 全局注意力
泛化差 光照敏感 长距弱 计算重 鲁棒性强

为什么 Transformer 更适合疲劳检测?

CNN 的局限

问题 说明
局部感受野 CNN 只能捕获局部特征,难以建模”打哈欠 + 眼睛闭合”的关联
深度依赖 需要很深的网络才能获得全局上下文
计算效率 深层网络计算成本高

Transformer 的优势

特性 说明
全局自注意力 一次建模整张图像的所有关系
长距依赖 捕获眼睛、嘴巴、眉毛的协同变化
可解释性 Class Activation Mapping (CAM) 可视化决策区域

自注意力机制

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
class MultiHeadSelfAttention(nn.Module):
"""
Transformer 自注意力核心

优势:能够关联眼睛闭合、嘴巴张开、眉毛皱起等
空间上远距离的特征
"""
def __init__(self, embed_dim, num_heads):
super().__init__()
self.num_heads = num_heads
self.head_dim = embed_dim // num_heads

self.qkv = nn.Linear(embed_dim, 3 * embed_dim)
self.proj = nn.Linear(embed_dim, embed_dim)

def forward(self, x):
B, N, C = x.shape # Batch, Num_patches, Channels

# 生成 Query, Key, Value
qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, self.head_dim)
q, k, v = qkv.permute(2, 0, 3, 1, 4) # (3, B, Heads, N, Dim)

# 注意力分数:Query × Key
attn = (q @ k.transpose(-2, -1)) / (self.head_dim ** 0.5)
attn = attn.softmax(dim=-1)

# 加权求和:Attn × Value
x = (attn @ v).transpose(1, 2).reshape(B, N, C)

return self.proj(x)

ViT vs Swin Transformer 对比

架构差异

维度 ViT Swin Transformer
注意力范围 全局 局部窗口 + 跨窗口
计算复杂度 O(N²) O(N)
层次结构 单尺度 多尺度金字塔
适用场景 大数据集 小/中数据集
实时性 较慢 较快

ViT 架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
输入图像 (224×224)

Patch Embedding (16×16 patches → 196 tokens)

+ Positional Embedding

┌────────────────────────────┐
│ Transformer Encoder × 12 │
│ ├─ Multi-Head Attention │
│ ├─ Layer Norm │
│ ├─ MLP │
│ └─ Residual Connection │
└────────────────────────────┘

Classification Head

Open-Eyes / Close-Eyes

Swin Transformer 架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
输入图像 (224×224)

Patch Partition (4×4 patches)

┌─────────────────────────────────────┐
│ Stage 1: Linear Embedding │
│ └─ Swin Block × 2 (Window Attn) │
├─────────────────────────────────────┤
│ Stage 2: Patch Merging │
│ └─ Swin Block × 2 (Shifted Win) │
├─────────────────────────────────────┤
│ Stage 3: Patch Merging │
│ └─ Swin Block × 6 (Window Attn) │
├─────────────────────────────────────┤
│ Stage 4: Patch Merging │
│ └─ Swin Block × 2 (Shifted Win) │
└─────────────────────────────────────┘

Classification Head

Open-Eyes / Close-Eyes

实验结果对比

基准数据集

数据集 样本数 特点
MRL Eye 84,898 多光照、多角度、多分辨率
NTHU-DDD 66,521 真实驾驶场景、白天/夜间
CEW 27,200 野外场景、遮挡、表情变化

模型性能对比

模型 MRL 准确率 NTHU-DDD 准确率 CEW 准确率 参数量
PERCLOS 72% - - 0
VGG16 95.2% 93.1% 91.5% 134M
VGG19 97.3% 95.4% 93.2% 144M
ResNet50V2 96.8% 94.2% 92.1% 25M
EffRes-DrowsyNet 97.7% 92.7% 95.1% 混合
ViT-Base 98.5% 97.2% 95.8% 86M
Swin-Tiny 99.15% 98.1% 96.4% 28M

关键指标

模型 Accuracy Precision Recall F1-Score
ViT 99.15% 99.2% 99.1% 99.15%
Swin 98.8% 98.9% 98.7% 98.8%
VGG19 98.7% 98.5% 98.9% 98.7%

实时检测系统实现

系统架构

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
┌────────────────────────────────────────────────────────┐
│ 实时疲劳检测系统架构 │
├────────────────────────────────────────────────────────┤
│ │
│ 视频流 (30fps) │
│ ↓ │
│ ┌──────────────────┐ │
│ │ Haar Cascade │ → 人脸检测 │
│ │ 人脸/眼睛定位 │ │
│ └────────┬─────────┘ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ 眼部区域提取 │ → 左眼/右眼 ROI │
│ │ (224×224) │ │
│ └────────┬─────────┘ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ ViT/Swin 推理 │ → Open/Close 分类 │
│ │ (GPU/NPU) │ │
│ └────────┬─────────┘ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ 疲劳评分系统 │ │
│ │ score += 1 (闭眼)│ │
│ │ score -= 1 (睁眼)│ │
│ └────────┬─────────┘ │
│ ↓ │
│ ┌──────────────────┐ │
│ │ 阈值判断 │ │
│ │ score ≥ 15 → 警告│ │
│ └────────┬─────────┘ │
│ ↓ │
│ 警告输出 │
└────────────────────────────────────────────────────────┘

核心代码

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
class RealTimeDrowsinessDetector:
"""
实时疲劳检测系统
"""

def __init__(self, model_path, threshold=15):
self.model = self.load_model(model_path)
self.face_cascade = cv2.CascadeClassifier('haarcascade_frontalface.xml')
self.eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
self.threshold = threshold
self.score = 0

def detect(self, frame):
"""
单帧检测
"""
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

# 1. 人脸检测
faces = self.face_cascade.detectMultiScale(gray, 1.3, 5)

for (x, y, w, h) in faces:
roi_gray = gray[y:y+h, x:x+w]

# 2. 眼睛检测
eyes = self.eye_cascade.detectMultiScale(roi_gray)

for (ex, ey, ew, eh) in eyes:
# 提取眼部区域
eye_roi = roi_gray[ey:ey+eh, ex:ex+ew]

# 预处理
eye_input = self.preprocess(eye_roi)

# 3. 模型推理
prediction = self.model.predict(eye_input)

# 4. 更新评分
if prediction == 'Close-Eyes':
self.score += 1
else:
self.score = max(0, self.score - 1)

# 5. 阈值判断
if self.score >= self.threshold:
return self.trigger_alert()

return None

def preprocess(self, eye_roi):
"""
眼部图像预处理
"""
# 缩放
eye = cv2.resize(eye_roi, (224, 224))
# 归一化
eye = eye.astype(np.float32) / 255.0
# 增加通道维度
eye = np.stack([eye] * 3, axis=-1)
# 增加批次维度
eye = np.expand_dims(eye, axis=0)
return eye

def trigger_alert(self):
"""
触发警告
"""
return {
'alert': True,
'score': self.score,
'message': 'Drowsiness detected! Please take a break.'
}

Class Activation Mapping (CAM) 可视化

为什么 CAM 重要?

场景 说明
调试 验证模型是否关注正确区域
信任 用户理解模型决策依据
改进 发现模型偏见和问题

ViT CAM 示例

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
def generate_cam(model, image, target_class):
"""
生成 Class Activation Map

输出:热力图显示模型关注的区域
"""
# 前向传播,保存注意力权重
features, attentions = model.forward_with_attention(image)

# 获取最后一层注意力
last_attn = attentions[-1] # (B, Heads, N, N)

# 平均所有头
attn_map = last_attn.mean(dim=1) # (B, N, N)

# 提取 CLS token 对所有 patch 的注意力
cls_attn = attn_map[:, 0, 1:] # (B, N-1)

# 重塑为空间图
num_patches = int(np.sqrt(cls_attn.shape[1]))
cam = cls_attn.reshape(-1, num_patches, num_patches)

# 上采样到原图大小
cam = cv2.resize(cam, (224, 224))

# 归一化
cam = (cam - cam.min()) / (cam.max() - cam.min())

return cam

可视化结果分析

情况 CAM 关注区域 说明
睁眼 眼睛周围 正确识别眼睛开放
闭眼 眼睑区域 正确识别眼睛闭合
打哈欠 嘴巴 + 眼睛 捕获多区域协同
错误预测 背景/边缘 模型问题,需改进

PERCLOS 仍需保留

Transformer + PERCLOS 融合

方案 说明
纯 Transformer 99.15% 准确率,但缺乏时序信息
Transformer + PERCLOS 眼开闭分类 + 时间窗口计算
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
class HybridDrowsinessDetector:
"""
Transformer + PERCLOS 融合检测
"""

def __init__(self, model_path, window_size=60):
self.model = load_model(model_path)
self.window_size = window_size # 60 帧 = 2 秒 (30fps)
self.eye_states = deque(maxlen=window_size)

def update_perclos(self, eye_state):
"""
更新 PERCLOS 计算
"""
self.eye_states.append(eye_state)

if len(self.eye_states) < self.window_size:
return None

# PERCLOS = 闭眼帧数 / 总帧数
closed_count = sum(1 for s in self.eye_states if s == 'Close')
perclos = closed_count / self.window_size

return perclos

def classify_fatigue(self, perclos):
"""
根据 PERCLOS 值分类疲劳程度
"""
if perclos < 0.15:
return 'ALERT', perclos
elif perclos < 0.30:
return 'SLIGHT_DROWSY', perclos
elif perclos < 0.50:
return 'MODERATE_DROWSY', perclos
else:
return 'SEVERE_DROWSY', perclos

Euro NCAP 合规性

疲劳检测要求

要求 实现方案
检测精度 ViT/Swin 准确率 99%+
响应时间 ≤5 秒检测疲劳状态
误报率 Transformer 降低误报
多人口适应 数据增强 + 合成数据

验证场景

Euro NCAP 场景 测试内容
F-01 PERCLOS ≥ 30%,持续 5 秒
F-02 打哈欠连续 3 次
F-03 点头检测

开发启示

模型选型

场景 推荐模型
高精度要求 ViT-Base (99.15%)
实时性要求 Swin-Tiny (28M 参数)
资源受限 MobileNet + 蒸馏
嵌入式部署 Swin + 量化

部署优化

技术 效果
量化 INT8 模型缩小 4x,速度 +30%
剪枝 减少冗余注意力头
蒸馏 大模型 → 小模型
ONNX Runtime 优化推理引擎

数据需求

数据类型 数量 说明
真实数据 ≥5000 段 多场景/多人口
合成数据 按需 Anyverse 边缘场景
验证数据 ≥1000 人 公平性验证

参考资料

  1. Real-time driver drowsiness detection using transformer architectures - Nature Scientific Reports 2025
  2. EffRes-DrowsyNet - PMC
  3. A Survey on Drowsiness Detection - arXiv
  4. Appearance-based Gaze Estimation with Deep Learning - arXiv

开发启示: Transformer 架构将疲劳检测准确率从 CNN 的 92-97% 提升到 99.15%,核心优势是全局自注意力机制。但 PERCLOS 时序计算仍需保留,用于 Euro NCAP 场景的疲劳程度评估。实时部署推荐 Swin Transformer,平衡精度与效率。