MDERNet双分支情感识别:面部+驾驶行为融合在智能座舱中的应用

论文信息

项目 内容
标题 AI-enabled intelligent cockpit proactive affective interaction: middle-level feature fusion dual-branch deep learning network for driver emotion recognition
期刊 Advances in Manufacturing (Springer Nature)
发布 2024年9月4日 (2025年正式出版)
链接 https://link.springer.com/article/10.1007/s40436-024-00519-8
作者 Wu YZ, Li WB, Liu YJ et al.
核心 MDERNet: 双分支中层级特征融合的驾驶员情感识别

核心创新

提出 MDERNet(Multimodal Driver Emotion Recognition Network),采用中层级特征融合策略,将驾驶员面部表情特征与驾驶行为特征(刹车力度、方向盘转角、车辆姿态)在特征表示空间中融合,而非简单的早期拼接或晚期投票。

1. 融合策略对比

1.1 三种融合策略

策略 融合位置 优点 缺点 代表方法
早期融合 原始数据层 信息完全 模态异构难对齐 特征拼接
中期融合 特征表示层 平衡信息与抽象 需要精心设计 MDERNet
晚期融合 决策层 模块独立 丢失跨模态交互 投票/平均

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
"""
中期融合的优势分析
"""
mid_level_advantages = {
"信息保留": {
"early": "100% 原始信息,但模态异构",
"mid": "各模态提取有意义的特征后融合,信息保留约85%",
"late": "各模态独立决策,仅保留结果,跨模态交互丢失"
},
"计算效率": {
"early": "高(全模态联合处理)",
"mid": "中(各模态独立编码 + 融合层)",
"late": "低(各模态独立,仅结果融合)"
},
"跨模态交互": {
"early": "理论上有,实际被异构性阻碍",
"mid": "在特征空间中自然交互 ✓",
"late": "无跨模态交互"
},
"缺失模态": {
"early": "困难(需零填充)",
"mid": "可通过特征层zero-shot处理",
"late": "简单(忽略缺失模态决策)"
}
}

print("中期融合 (MDERNet) 优势:")
for aspect, comparison in mid_level_advantages.items():
print(f"\n{aspect}:")
for level, desc in comparison.items():
print(f" {level}: {desc}")

2. MDERNet 架构

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
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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Tuple

class MDERNet(nn.Module):
"""
MDERNet: 多模态驾驶员情感识别网络
=================================

论文核心架构

分支1: 面部表情分支
- 输入: 面部视频帧序列 [B, T, 3, H, W]
- 编码: 3D-CNN → 时序特征
- 输出: 面部情感特征 [B, D]

分支2: 驾驶行为分支
- 输入: 驾驶行为序列 [B, T, 4] (刹车, 油门, 方向盘, 速度)
- 编码: 1D-CNN + LSTM → 时序特征
- 输出: 驾驶行为特征 [B, D]

融合层: 中层级特征融合
- 方式: 双线性融合 + 交叉注意力
- 输出: 融合特征 [B, D]

分类头: 情感分类
- 输出: 7类情感 logits [B, 7]

Args:
face_dim: 面部特征维度
behavior_dim: 驾驶行为特征维度
fusion_dim: 融合后维度
num_emotions: 情感类别数
"""

def __init__(
self,
face_dim: int = 512,
behavior_dim: int = 128,
fusion_dim: int = 256,
num_emotions: int = 7,
num_behavior_features: int = 4, # brake, throttle, steering, speed
sequence_length: int = 30 # 1秒@30fps
):
super().__init__()

# ===== 分支1: 面部表情分支 =====
self.face_branch = FaceExpressionBranch(
output_dim=face_dim,
sequence_length=sequence_length
)

# ===== 分支2: 驾驶行为分支 =====
self.behavior_branch = DrivingBehaviorBranch(
input_dim=num_behavior_features,
output_dim=behavior_dim,
sequence_length=sequence_length
)

# ===== 中层级融合 =====
self.fusion = MidLevelFusion(
face_dim=face_dim,
behavior_dim=behavior_dim,
output_dim=fusion_dim
)

# ===== 分类头 =====
self.classifier = nn.Sequential(
nn.Linear(fusion_dim, fusion_dim),
nn.LayerNorm(fusion_dim),
nn.GELU(),
nn.Dropout(0.2),
nn.Linear(fusion_dim, num_emotions)
)

def forward(
self,
face_frames: torch.Tensor,
behavior_data: torch.Tensor
) -> dict:
"""
前向传播

Args:
face_frames: [B, T, 3, H, W] 面部视频
behavior_data: [B, T, 4] 驾驶行为序列

Returns:
emotions: [B, 7] 情感logits
face_feat: [B, face_dim] 面部特征
behavior_feat: [B, behavior_dim] 行为特征
fused_feat: [B, fusion_dim] 融合特征
"""
# 1. 双分支编码
face_feat = self.face_branch(face_frames)
behavior_feat = self.behavior_branch(behavior_data)

# 2. 中层级融合
fused_feat = self.fusion(face_feat, behavior_feat)

# 3. 分类
emotions = self.classifier(fused_feat)

return {
"emotions": emotions,
"face_feat": face_feat,
"behavior_feat": behavior_feat,
"fused_feat": fused_feat
}


class FaceExpressionBranch(nn.Module):
"""面部表情分支: 3D-CNN"""

def __init__(self, output_dim: int = 512, sequence_length: int = 30):
super().__init__()

# 轻量3D-CNN
self.conv1 = nn.Conv3d(3, 32, (3, 3, 3), stride=(1, 2, 2), padding=(1, 1, 1))
self.bn1 = nn.BatchNorm3d(32)
self.conv2 = nn.Conv3d(32, 64, (3, 3, 3), stride=(1, 2, 2), padding=(1, 1, 1))
self.bn2 = nn.BatchNorm3d(64)
self.conv3 = nn.Conv3d(64, 128, (3, 3, 3), stride=(1, 2, 2), padding=(1, 1, 1))
self.bn3 = nn.BatchNorm3d(128)

self.pool = nn.AdaptiveAvgPool3d((1, 1, 1))
self.fc = nn.Linear(128, output_dim)

def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: [B, T, 3, H, W] → [B, 3, T, H, W]
"""
x = x.permute(0, 2, 1, 3, 4) # [B, C, T, H, W]

x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
x = F.relu(self.bn3(self.conv3(x)))

x = self.pool(x).flatten(1)
return self.fc(x)


class DrivingBehaviorBranch(nn.Module):
"""驾驶行为分支: 1D-CNN + LSTM"""

def __init__(self, input_dim: int = 4, output_dim: int = 128, sequence_length: int = 30):
super().__init__()

# 1D-CNN 提取局部模式
self.conv1 = nn.Conv1d(input_dim, 32, 3, padding=1)
self.conv2 = nn.Conv1d(32, 64, 3, padding=1)

# LSTM 提取时序依赖
self.lstm = nn.LSTM(64, output_dim, batch_first=True, num_layers=2)

def forward(self, x: torch.Tensor) -> torch.Tensor:
"""
Args:
x: [B, T, 4] 驾驶行为序列
"""
# 1D-CNN: [B, T, 4] → [B, 4, T] → conv → [B, 64, T] → [B, T, 64]
x = x.permute(0, 2, 1)
x = F.relu(self.conv1(x))
x = F.relu(self.conv2(x))
x = x.permute(0, 2, 1) # [B, T, 64]

# LSTM: [B, T, 64] → [B, T, output_dim] → [B, output_dim]
out, (h, c) = self.lstm(x)
return out[:, -1, :] # 取最后时间步


class MidLevelFusion(nn.Module):
"""中层级特征融合"""

def __init__(self, face_dim: int, behavior_dim: int, output_dim: int):
super().__init__()

# 投影到统一维度
self.face_proj = nn.Linear(face_dim, output_dim)
self.behavior_proj = nn.Linear(behavior_dim, output_dim)

# 交叉注意力
self.cross_attn_f2b = nn.MultiheadAttention(output_dim, 4, batch_first=True)
self.cross_attn_b2f = nn.MultiheadAttention(output_dim, 4, batch_first=True)

# 融合门控
self.gate = nn.Sequential(
nn.Linear(output_dim * 2, output_dim),
nn.Sigmoid()
)

# 输出
self.output = nn.Sequential(
nn.Linear(output_dim, output_dim),
nn.LayerNorm(output_dim),
nn.GELU()
)

def forward(self, face_feat: torch.Tensor, behavior_feat: torch.Tensor) -> torch.Tensor:
# 投影
f = self.face_proj(face_feat).unsqueeze(1) # [B, 1, D]
b = self.behavior_proj(behavior_feat).unsqueeze(1) # [B, 1, D]

# 交叉注意力
f_enhanced, _ = self.cross_attn_f2b(f, b, b) # Face attends to Behavior
b_enhanced, _ = self.cross_attn_b2f(b, f, f) # Behavior attends to Face

f_out = f_enhanced.squeeze(1)
b_out = b_enhanced.squeeze(1)

# 门控融合
gate = self.gate(torch.cat([f_out, b_out], dim=-1))
fused = gate * f_out + (1 - gate) * b_out

return self.output(fused)

# 测试
if __name__ == "__main__":
model = MDERNet(
face_dim=512,
behavior_dim=128,
fusion_dim=256,
num_emotions=7
)

# 模拟输入
face = torch.randn(4, 30, 3, 64, 64) # 30帧, 64x64
behavior = torch.randn(4, 30, 4) # 30步, 4维

out = model(face, behavior)

total_params = sum(p.numel() for p in model.parameters())
print(f"MDERNet 双分支情感识别")
print(f"输入: face={face.shape}, behavior={behavior.shape}")
print(f"输出: {out['emotions'].shape}")
print(f"总参数: {total_params:,} ({total_params/1e6:.2f}M)")
print(f"面部特征: {out['face_feat'].shape}")
print(f"行为特征: {out['behavior_feat'].shape}")
print(f"融合特征: {out['fused_feat'].shape}")

3. 驾驶行为特征详解

3.1 四维驾驶行为输入

维度 来源 采样率 物理意义 情感关联
刹车力度 制动踏板压力传感器 30Hz 紧急/平稳制动 急刹→愤怒/恐惧
油门深度 油门踏板位置传感器 30Hz 加速意图 深油门→急躁/兴奋
方向盘转角 方向盘角度传感器 30Hz 转向意图 频繁微调→焦虑
车速 车速传感器/OBD 30Hz 行驶速度 超速→急躁/愤怒

3.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
"""
驾驶行为模式 → 情感推断
"""
behavior_emotion_mapping = {
"aggressive_braking": {
"pattern": "频繁急刹 (减速度 >3m/s²)",
"emotions": ["angry", "fear", "surprise"],
"safety_level": "warning"
},
"rapid_acceleration": {
"pattern": "频繁深油门 (加速度 >3m/s²)",
"emotions": ["angry", "happy(excited)"],
"safety_level": "warning"
},
"erratic_steering": {
"pattern": "频繁大角度转向修正 (>15°/s)",
"emotions": ["fear", "sad(anxious)"],
"safety_level": "alert"
},
"speeding": {
"pattern": "持续超速 (>限速+10%)",
"emotions": ["angry", "happy(confident)"],
"safety_level": "warning"
},
"smooth_driving": {
"pattern": "平稳制动+均匀加速+微调方向",
"emotions": ["neutral", "happy(calm)"],
"safety_level": "normal"
},
"hesitant_driving": {
"pattern": "频繁轻刹+低速行驶+犹豫转向",
"emotions": ["fear", "sad(uncertain)"],
"safety_level": "monitor"
}
}

print("驾驶行为→情感映射:")
for pattern, info in behavior_emotion_mapping.items():
print(f"\n {pattern}:")
print(f" 特征: {info['pattern']}")
print(f" 情感: {', '.join(info['emotions'])}")
print(f" 安全: {info['safety_level']}")

4. 实验结果

4.1 性能对比

方法 融合策略 面部模态 行为模态 准确率 参数量
Face-only - ✅ ❌ 63.8% 8.2M
Behavior-only - ❌ ✅ 41.2% 1.5M
Early Concat 早期 ✅ ✅ 68.5% 9.7M
Late Voting 晚期 ✅ ✅ 71.3% 9.7M (2×模型)
MDERNet 中期 ✅ ✅ 78.6% 10.8M

4.2 消融实验

设置 准确率 变化
完整 MDERNet 78.6% -
无交叉注意力 74.2% -4.4%
无门控融合 75.1% -3.5%
无 LSTM 时序 72.3% -6.3%
无 3D-CNN (用2D) 76.8% -1.8%

5. IMS 集成方案

5.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
"""
IMS 驾驶行为数据获取接口
"""

class DrivingBehaviorCollector:
"""
驾驶行为数据采集器

与车辆 CAN 总线 / OBD 接口对接
"""

def __init__(self, config):
self.buffer_size = 30 # 1秒@30Hz
self.buffer = {
'brake': [],
'throttle': [],
'steering': [],
'speed': []
}

def update(self, can_message):
"""从 CAN 总线消息更新数据"""
if can_message.id == 0x1A4: # 制动压力
self.buffer['brake'].append(can_message.data[0] / 255.0)
elif can_message.id == 0x1A5: # 油门位置
self.buffer['throttle'].append(can_message.data[0] / 255.0)
elif can_message.id == 0x1A6: # 方向盘转角
angle = int.from_bytes(can_message.data[:2], 'big') - 32767
self.buffer['steering'].append(angle / 720.0) # 归一化到[-1,1]
elif can_message.id == 0x1A7: # 车速
self.buffer['speed'].append(int.from_bytes(can_message.data[:2], 'big') / 100.0)

# 维护缓冲区
for key in self.buffer:
if len(self.buffer[key]) > self.buffer_size:
self.buffer[key] = self.buffer[key][-self.buffer_size:]

def get_sequence(self) -> torch.Tensor:
"""获取当前行为序列 [1, 30, 4]"""
if len(self.buffer['brake']) < self.buffer_size:
return None

seq = torch.stack([
torch.tensor(self.buffer['brake']),
torch.tensor(self.buffer['throttle']),
torch.tensor(self.buffer['steering']),
torch.tensor(self.buffer['speed'])
], dim=-1)

return seq.unsqueeze(0) # [1, 30, 4]

# CAN信号映射表
CAN_SIGNALS = {
"0x1A4": {"name": "BrakePressure", "freq": 30, "range": "0-255", "unit": "归一化"},
"0x1A5": {"name": "ThrottlePosition", "freq": 30, "range": "0-255", "unit": "归一化"},
"0x1A6": {"name": "SteeringAngle", "freq": 30, "range": "-720~720", "unit": "度"},
"0x1A7": {"name": "VehicleSpeed", "freq": 30, "range": "0-65535", "unit": "cm/s"}
}

print("驾驶行为 CAN 信号:")
for msg_id, info in CAN_SIGNALS.items():
print(f" {msg_id}: {info['name']}, {info['freq']}Hz, {info['range']} {info['unit']}")

5.2 部署架构

6. 与纯视觉方法对比

维度 纯面部表情 MDERNet (面部+行为)
准确率 63.8% 78.6% (+14.8%)
面部遮挡 严重下降 行为特征补偿
低光环境 严重下降 行为特征不受影响
驾驶员身份 需要个性化 行为模式更通用
硬件成本 仅摄像头 摄像头 + CAN接口
实时性 8ms 12ms (+4ms)
部署难度 低 中 (需CAN对接)

7. IMS 开发启示

7.1 核心价值

启示 说明 优先级
行为数据是情感识别的重要补充 +14.8% 准确率提升 🔴 高
CAN总线数据零成本 现有车辆已具备,无需额外硬件 🔴 高
中期融合最优 优于早期拼接和晚期投票 🟡 中
时序建模关键 LSTM 对行为模式建模贡献大 🟡 中
交叉注意力有效 跨模态交互显著提升性能 🟡 中

7.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
"""
IMS 情感模块开发路线
"""

roadmap = {
"Phase 1 (2周)": {
"目标": "面部情感基线",
"任务": [
"部署增强ResNet+WCSA (前一篇论文)",
"集成DMS摄像头输入",
"建立7类情感分类基线"
],
"指标": "准确率 >65%"
},
"Phase 2 (3周)": {
"目标": "行为特征集成",
"任务": [
"CAN总线数据采集接口",
"驾驶行为序列预处理",
"行为分支CNN+LSTM训练"
],
"指标": "行为分支单独 >40%"
},
"Phase 3 (3周)": {
"目标": "MDERNet融合",
"任务": [
"中层级融合模块实现",
"交叉注意力训练",
"端到端微调"
],
"指标": "融合准确率 >75%"
},
"Phase 4 (2周)": {
"目标": "边缘部署",
"任务": [
"INT8量化",
"QNN SDK适配",
"实时性验证"
],
"指标": "延迟 <15ms"
}
}

print("情感模块开发路线:")
for phase, info in roadmap.items():
print(f"\n{phase}: {info['目标']}")
for task in info['任务']:
print(f" - {task}")
print(f" 指标: {info['指标']}")

8. 总结

MDERNet 的核心贡献:

  1. 中期融合最优 — 78.6% 准确率,显著优于早期(68.5%)和晚期(71.3%)
  2. 双分支设计 — 面部3D-CNN + 行为CNN+LSTM,各自提取最优特征
  3. 交叉注意力 — 跨模态交互在特征空间中自然发生
  4. 门控融合 — 自适应平衡两个分支的贡献
  5. CAN数据零成本 — 利用现有车辆传感器,无需额外硬件

对 IMS 的核心价值:

  • 驾驶行为数据大幅提升情感识别准确率
  • CAN接口在量产车中零成本获取
  • 与现有DMS系统无缝集成
  • 双分支架构容错性好

论文链接: https://link.springer.com/article/10.1007/s40436-024-00519-8