多状态驾驶员监控:基于扩散增强的疲劳/酒驾/认知分心统一检测框架

论文信息:

  • 标题:Multi-state Driver Monitoring via Identity-Preserving Diffusion Augmentation and a CNN–Transformer Architecture
  • 作者:Linh T. P. Le, Kha Tu Huynh(越南国立大学)
  • 会议:ICCIES 2026 (Computational Intelligence in Engineering Science)
  • 发表:2026年4月3日
  • DOI:10.1007/978-3-032-21631-1_37

核心问题

痛点: 疲劳、酒驾、认知分心在视觉特征上高度重叠,现有系统难以区分

状态 共同视觉特征 区分难点
疲劳 眼睛闭合、眨眼频率变化 PERCLOS特征与认知分心重叠
酒驾 眼睑下垂、面部松弛、扫视异常 与疲劳状态高度相似
认知分心 视线偏移、眨眼频率变化 无明显物理特征,需时序分析

数据困境:

  • 酒驾数据极度稀缺(伦理问题,无法采集真实数据)
  • 现有研究多关注单一状态,无法泛化到实际驾驶场景
  • 状态重叠导致误判率高

核心创新

1. 统一多状态监控框架

架构设计:

1
2
3
4
5
6
7
输入视频帧序列

MobileNetV2 + SE Block(空间特征提取)

Lightweight Transformer(时序建模)

7状态分类输出

7个状态类别:

类别 说明
Normal 正常驾驶
Fatigue 疲劳
Alcohol Impaired 酒驾损伤
Cognitive Distraction 认知分心
Visual Distraction 视觉分心
Manual Distraction 手动分心
Unknown 未知状态

2. 身份保持扩散增强(核心贡献)

问题: 真实酒驾数据无法获取

解决方案: 使用扩散模型从疲劳数据生成酒驾数据

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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import torch
from diffusers import StableDiffusionPipeline
import mediapipe as mp

class IdentityPreservingAugmentation:
"""
论文核心方法:身份保持扩散增强

功能:从疲劳图像生成酒驾图像,保持身份和光照
"""

def __init__(self, model_path: str = "runwayml/stable-diffusion-v1-5"):
self.pipe = StableDiffusionPipeline.from_pretrained(
model_path,
torch_dtype=torch.float16
).to("cuda")

# 初始化面部检测
self.face_mesh = mp.solutions.face_mesh.FaceMesh(
static_image_mode=True,
max_num_faces=1
)

def extract_facial_landmarks(self, image):
"""
提取468个面部地标点

Args:
image: RGB图像, shape=(H, W, 3)

Returns:
landmarks: 地标坐标, shape=(468, 2)
"""
results = self.face_mesh.process(image)
if not results.multi_face_landmarks:
return None

landmarks = results.multi_face_landmarks[0]
h, w = image.shape[:2]

points = []
for landmark in landmarks.landmark:
points.append([int(landmark.x * w), int(landmark.y * h)])

return np.array(points)

def create_facial_mask(self, landmarks, image_shape):
"""
创建面部区域掩码

仅覆盖眼睛、嘴巴、面部轮廓区域
保持背景、发型、姿态不变
"""
h, w = image_shape[:2]
mask = np.zeros((h, w), dtype=np.uint8)

# 关键区域索引(基于MediaPipe Face Mesh)
eye_indices = [33, 133, 362, 263, 159, 145, 386, 374] # 左右眼
mouth_indices = [61, 291, 78, 308, 13, 14] # 嘴巴
face_oval = [10, 338, 297, 332, 284, 251, 389, 356,
454, 323, 361, 288, 397, 365, 379, 378,
400, 377, 152, 148, 176, 149, 150, 136,
172, 58, 132, 93, 234, 127, 162, 21] # 面部轮廓

# 合并所有区域
key_points = np.array(landmarks[eye_indices + mouth_indices + face_oval])

# 创建凸包掩码
from scipy.spatial import ConvexHull
hull = ConvexHull(key_points)

# 填充掩码
cv2.fillConvexPoly(mask, key_points[hull.vertices], 255)

return mask

def generate_alcohol_impaired(
self,
fatigue_image,
identity_embedding,
num_inference_steps: int = 50,
guidance_scale: float = 7.5
):
"""
从疲劳图像生成酒驾图像

Args:
fatigue_image: 疲劳状态图像
identity_embedding: 身份文本嵌入(通过文本反演学习)
num_inference_steps: 扩散步数
guidance_scale: 分类器引导强度

Returns:
alcohol_image: 生成的酒驾图像
"""
# 1. 提取面部地标
landmarks = self.extract_facial_landmarks(fatigue_image)

# 2. 创建面部掩码
mask = self.create_facial_mask(landmarks, fatigue_image.shape)

# 3. 构建提示词(使用学习到的酒驾嵌入)
prompt = "alcohol impaired driver with droopy eyelids and relaxed facial muscles, photo of <alcohol-concept>"

# 4. 图像修复生成
result = self.pipe(
prompt=prompt,
image=Image.fromarray(fatigue_image),
mask_image=Image.fromarray(mask),
num_inference_steps=num_inference_steps,
guidance_scale=guidance_scale,
# 注入身份嵌入
token_embeddings=identity_embedding
)

return result.images[0]


# 使用示例
if __name__ == "__main__":
augmentor = IdentityPreservingAugmentation()

# 加载疲劳图像
fatigue_img = cv2.imread("fatigue_driver.jpg")
fatigue_img = cv2.cvtColor(fatigue_img, cv2.COLOR_BGR2RGB)

# 加载预训练的身份嵌入
identity_emb = torch.load("identity_embedding.pt")

# 生成酒驾图像
alcohol_img = augmentor.generate_alcohol_impaired(
fatigue_img,
identity_emb,
num_inference_steps=50
)

alcohol_img.save("alcohol_driver_synthetic.jpg")
print("生成完成!")

3. CNN-Transformer混合架构

空间编码器:MobileNetV2 + SE Block

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
import torch
import torch.nn as nn
from torchvision.models import mobilenet_v2

class SpatialEncoder(nn.Module):
"""
空间特征提取:MobileNetV2 + Squeeze-and-Excitation

输入:单帧图像 (B, 3, 224, 224)
输出:空间特征 (B, 1280, 7, 7)
"""

def __init__(self, pretrained: bool = True):
super().__init__()

# 加载预训练MobileNetV2
mobilenet = mobilenet_v2(pretrained=pretrained)

# 移除分类头
self.features = mobilenet.features

# 添加SE块增强通道注意力
self.se_block = SEBlock(1280, reduction=16)

def forward(self, x):
"""
Args:
x: 输入图像, shape=(B, 3, 224, 224)

Returns:
features: 空间特征, shape=(B, 1280, 7, 7)
"""
features = self.features(x)
features = self.se_block(features)

return features


class SEBlock(nn.Module):
"""
Squeeze-and-Excitation Block

论文:Hu et al., "Squeeze-and-Excitation Networks", CVPR 2018

功能:通道注意力,增强重要特征通道
"""

def __init__(self, channels: int, reduction: int = 16):
super().__init__()

self.squeeze = nn.AdaptiveAvgPool2d(1)
self.excitation = nn.Sequential(
nn.Linear(channels, channels // reduction, bias=False),
nn.ReLU(inplace=True),
nn.Linear(channels // reduction, channels, bias=False),
nn.Sigmoid()
)

def forward(self, x):
B, C, H, W = x.size()

# Squeeze: 全局平均池化
y = self.squeeze(x).view(B, C)

# Excitation: 通道权重学习
y = self.excitation(y).view(B, C, 1, 1)

# Scale: 重新加权
return x * y.expand_as(x)

时序编码器:轻量级Transformer

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
import torch
import torch.nn as nn
import math

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

为Transformer添加时序位置信息
"""

def __init__(self, d_model: int, max_len: int = 500):
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):
"""
Args:
x: 输入序列, shape=(B, T, D)

Returns:
x + pe: 添加位置编码的序列
"""
return x + self.pe[:, :x.size(1)]


class TemporalEncoder(nn.Module):
"""
时序建模:轻量级Transformer

输入:空间特征序列 (B, T, 1280)
输出:时序特征 (B, T, 256)
"""

def __init__(
self,
input_dim: int = 1280,
d_model: int = 256,
nhead: int = 4,
num_layers: int = 2,
dropout: float = 0.1
):
super().__init__()

# 输入投影
self.input_proj = nn.Linear(input_dim, d_model)

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

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

def forward(self, x):
"""
Args:
x: 空间特征序列, shape=(B, T, 1280)

Returns:
temporal_features: 时序特征, shape=(B, T, 256)
"""
# 投影到模型维度
x = self.input_proj(x)

# 添加位置编码
x = self.pos_encoder(x)

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

return x


class MultiStateDMS(nn.Module):
"""
完整的多状态驾驶员监控系统

整合空间编码器 + 时序编码器 + 分类头
"""

def __init__(
self,
num_classes: int = 7,
seq_length: int = 30, # 30帧序列(1秒@30fps)
pretrained: bool = True
):
super().__init__()

self.seq_length = seq_length

# 空间编码器
self.spatial_encoder = SpatialEncoder(pretrained=pretrained)

# 时序编码器
self.temporal_encoder = TemporalEncoder(
input_dim=1280,
d_model=256,
nhead=4,
num_layers=2
)

# 分类头
self.classifier = nn.Sequential(
nn.Linear(256, 128),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(128, num_classes)
)

def forward(self, x):
"""
Args:
x: 视频序列, shape=(B, T, 3, 224, 224)

Returns:
logits: 状态分类, shape=(B, T, num_classes)
"""
B, T, C, H, W = x.size()

# 展平时间维度
x = x.view(B * T, C, H, W)

# 空间特征提取
spatial_features = self.spatial_encoder(x) # (B*T, 1280, 7, 7)

# 全局平均池化
spatial_features = spatial_features.mean(dim=[2, 3]) # (B*T, 1280)

# 恢复时间维度
spatial_features = spatial_features.view(B, T, -1) # (B, T, 1280)

# 时序编码
temporal_features = self.temporal_encoder(spatial_features) # (B, T, 256)

# 分类
logits = self.classifier(temporal_features) # (B, T, num_classes)

return logits


# 模型测试
if __name__ == "__main__":
model = MultiStateDMS(num_classes=7, seq_length=30)

# 模拟输入:batch=2, 30帧, RGB 224x224
x = torch.randn(2, 30, 3, 224, 224)

# 前向传播
output = model(x)

print(f"输入形状: {x.shape}")
print(f"输出形状: {output.shape}")
print(f"模型参数量: {sum(p.numel() for p in model.parameters()) / 1e6:.2f}M")

# 预期输出
# 输入形状: torch.Size([2, 30, 3, 224, 224])
# 输出形状: torch.Size([2, 30, 7])
# 模型参数量: ~5.2M

实验结果

数据集

数据集 样本数 用途
DMD (Driver Monitoring Dataset) 31,500 训练+验证
合成酒驾数据 5,200 扩散增强生成
测试集 3,500 七状态分类测试

性能指标

指标
测试准确率 97.37%
宏平均F1 ≈0.97
单帧推理速度 32 FPS (RTX 3080)
序列推理速度 28 FPS (30帧序列)

消融实验

配置 准确率 F1
仅MobileNetV2 89.2% 0.87
+ SE Block 92.1% 0.90
+ Transformer 95.3% 0.94
+ 扩散增强 97.37% 0.97

各状态性能

状态 Precision Recall F1
Normal 98.5% 99.1% 0.988
Fatigue 96.2% 95.8% 0.960
Alcohol Impaired 95.8% 94.3% 0.951
Cognitive Distraction 94.1% 93.2% 0.936
Visual Distraction 97.5% 98.0% 0.977
Manual Distraction 98.2% 97.6% 0.979
Unknown 92.3% 91.8% 0.920

IMS开发启示

1. 数据增强策略

当前问题: IMS缺乏酒驾检测数据

解决方案: 采用扩散增强生成合成数据

步骤 操作 工具
1 收集疲劳/分心数据 现有DMS数据集
2 训练文本反演嵌入 Stable Diffusion + “alcohol-impaired”
3 生成合成酒驾数据 面部地标引导修复
4 数据验证与筛选 人工审核 + 自动质量评估
5 模型训练 加入酒驾类别

代码实现路径:

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
# 1. 准备疲劳数据集
mkdir -p data/fatigue_images

# 2. 训练文本反演嵌入
accelerate launch textual_inversion.py \
--pretrained_model_name_or_path="runwayml/stable-diffusion-v1-5" \
--train_data_dir="data/fatigue_images" \
--learnable_property="object" \
--placeholder_token="<alcohol-driver>" \
--initializer_token="driver" \
--resolution=512 \
--train_batch_size=8 \
--gradient_accumulation_steps=4 \
--max_train_steps=3000 \
--learning_rate=5.0e-04 \
--scale_lr \
--lr_scheduler="constant" \
--lr_warmup_steps=0 \
--output_dir="embeddings/alcohol_concept"

# 3. 生成合成数据
python generate_synthetic.py \
--input_dir="data/fatigue_images" \
--output_dir="data/synthetic_alcohol" \
--embedding_path="embeddings/alcohol_concept/learned_embeds.bin" \
--num_images_per_input=5

2. 多状态统一模型

架构选择:

组件 推荐方案 理由
空间编码器 MobileNetV2 + SE 轻量高效,适合嵌入式部署
时序编码器 2层Transformer 平衡精度与速度
序列长度 30帧(1秒) 捕捉时序特征,实时性好
分类头 2层MLP 简单有效

部署到高通QCS8255:

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
# ONNX导出
import torch.onnx

model = MultiStateDMS(num_classes=7, seq_length=30)
model.eval()

# 模拟输入
dummy_input = torch.randn(1, 30, 3, 224, 224)

# 导出ONNX
torch.onnx.export(
model,
dummy_input,
"multi_state_dms.onnx",
opset_version=11,
input_names=['video_sequence'],
output_names=['state_logits'],
dynamic_axes={
'video_sequence': {0: 'batch_size'},
'state_logits': {0: 'batch_size'}
}
)

# Qualcomm SNPE量化
snpe-pytorch-to-dlc \
--input_network multi_state_dms.onnx \
--input_dim video_sequence 1,30,3,224,224 \
--output_path multi_state_dms.dlc

snpe-dlc-quantize \
--input_dlc multi_state_dms.dlc \
--input_list input_list.txt \
--output_dlc multi_state_dms_quantized.dlc

3. 认知分心检测突破

论文贡献: 认知分心F1达到0.936,接近疲劳检测性能

关键技术:

要素 实现方式
视线模式分析 Transformer捕捉注视轨迹异常
时序依赖建模 30帧窗口识别分心模式
与疲劳区分 眨眼频率 + 眼睑开度时序特征

IMS优先级:

阶段 功能 依据
Phase 1 疲劳 + 视觉分心 成熟技术,高准确率
Phase 2 认知分心 论文方法已验证
Phase 3 酒驾检测 使用扩散增强数据训练

与竞品对比

方案 支持状态数 酒驾检测 认知分心 准确率
本论文 7 ✅ 扩散增强 97.37%
Smart Eye 5 ✅ 眼动分析 ⚠️ 有限 ~95%
Seeing Machines 4 ⚠️ 实验中 ~93%
传统CNN 3-4 ~90%

关键参考文献

  1. 扩散模型: Ho et al., “Denoising Diffusion Probabilistic Models”, NeurIPS 2020
  2. 文本反演: Gal et al., “An Image is Worth One Word: Personalizing Text-to-Image Generation”, arXiv 2022
  3. SE-Net: Hu et al., “Squeeze-and-Excitation Networks”, CVPR 2018
  4. DMD数据集: Ortega et al., “DMD: A Large-Scale Multi-Modal Driver Monitoring Dataset”, ECCV 2020
  5. 酒驾面部估计: Keshtkaran et al., “Estimating Blood Alcohol Level Through Facial Features”, WACV 2024

总结

维度 核心贡献
问题 首次解决疲劳/酒驾/认知分心的视觉重叠问题
方法 扩散增强 + CNN-Transformer混合架构
数据 创造性解决酒驾数据稀缺问题
性能 七状态分类准确率97.37%,F1≈0.97
IMS启示 提供完整的数据增强和模型架构路线

下一步行动:

  1. 实现扩散增强流程,生成酒驾合成数据
  2. 训练多状态DMS模型
  3. 在高通平台部署验证
  4. 对接Euro NCAP 2026测试场景

发布时间: 2026-04-20
标签: #DMS #酒驾检测 #认知分心 #扩散模型 #Transformer #EuroNCAP