SoundMHPE:声学多人3D姿态估计——ECCV 2026论文解读与IMS OOP检测新思路

论文信息

项目 内容
标题 Sound-based Multi-Person 3D Pose Estimation
作者 Yuto Shibata, Go Irie, Akisato Kimura (NTT), Yoshimitsu Aoki, Mariko Isogawa
机构 Keio University, Tokyo University of Science, NTT Inc.
会议 ECCV 2026
arXiv 2609.04902
项目页 https://oumi03.github.io/sound-mhpe/
数据集 AMP dataset (6小时, 432K帧, 最多3人)

核心创新

首次实现仅用声学信号估计多人3D姿态。 这意味着:

  1. 无需摄像头 — 完全隐私保护的姿态感知方案
  2. 不受光照影响 — 黑暗中同样工作
  3. 可穿透金属障碍 — 声学波长较长,能绕过金属遮挡物
  4. 多人同时估计 — 支持同时追踪多个乘员姿态

与现有方法对比

方法 光照鲁棒 遮挡鲁棒 隐私保护 多人支持 金属穿透
RGB 图像 ❌ ❌ ❌ ✅ ❌
RF/WiFi 信号 ✅ 部分 ✅ ✅ ❌(水/金属)
mmWave 雷达 ✅ ✅ ✅ ✅ ❌
UWB 雷达 ✅ ✅ ✅ ✅ ❌
声学信号 (本文) ✅ ✅ ✅ ✅ ✅

方法详解

整体架构

1. 主动声学感知原理

系统采用主动声学感知方式:

  • 扬声器发射已知信号(如chirp信号)
  • 麦克风接收经过人体反射/散射后的信号
  • 接收信号中包含了人体姿态相关的声学特征

物理原理:人体不同部位对声波的反射特性不同,当人移动时,反射路径和相位发生变化,这些变化被编码在接收信号中。

2. Acoustic Multi-scale Encoder

核心挑战:多人场景下,声学信号是多人运动特征的叠加,加上多体反射导致的复杂传播延迟。

解决方案:多分辨率STFT(短时傅里叶变换)

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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import torch
import torch.nn as nn
import torch.nn.functional as F

class AcousticMultiScaleEncoder(nn.Module):
"""
多尺度声学编码器

论文Section 3.2实现
使用不同窗口大小的STFT提取互补的时频特征

Args:
signal_length: 输入信号长度
n_persons: 最大人数
n_joints: 关芽数(默认17)
"""

def __init__(self, signal_length=16000, n_persons=3, n_joints=17):
super().__init__()
# 短窗口STFT - 捕获高时间分辨率
# 窗口大小: 512 samples (~32ms @16kHz)
self.short_window = 512
self.short_hop = 160 # 10ms hop

# 长窗口STFT - 捕获高频率分辨率
# 窗口大小: 2048 samples (~128ms @16kHz)
self.long_window = 2048
self.long_hop = 320 # 20ms hop

# 特征维度
self.short_freq_bins = self.short_window // 2 + 1 # 257
self.long_freq_bins = self.long_window // 2 + 1 # 1025

# CNN骨干网络(类似ResNet)
self.short_cnn = self._make_cnn_encoder(self.short_freq_bins)
self.long_cnn = self._make_cnn_encoder(self.long_freq_bins)

# 融合层
self.fusion = nn.Sequential(
nn.Conv2d(256 * 2, 256, kernel_size=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True)
)

def _make_cnn_encoder(self, freq_bins):
"""构建CNN编码器"""
return nn.Sequential(
# Input: (1, freq_bins, T_frames)
nn.Conv2d(1, 64, kernel_size=(3, 3), padding=(1, 1)),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d((2, 2)),

nn.Conv2d(64, 128, kernel_size=(3, 3), padding=(1, 1)),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.MaxPool2d((2, 2)),

nn.Conv2d(128, 256, kernel_size=(3, 3), padding=(1, 1)),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
nn.MaxPool2d((2, 2)),

nn.Conv2d(256, 256, kernel_size=(3, 3), padding=(1, 1)),
nn.BatchNorm2d(256),
nn.ReLU(inplace=True),
)

def compute_stft(self, x, window_size, hop_size):
"""计算STFT"""
window = torch.hann_window(window_size, device=x.device)
stft = torch.stft(
x,
n_fft=window_size,
hop_length=hop_size,
win_length=window_size,
window=window,
return_complex=True
)
# 取幅度谱
magnitude = torch.abs(stft)
# log幅度
magnitude = torch.log1p(magnitude)
return magnitude.unsqueeze(1) # (B, 1, F, T)

def forward(self, x):
"""
Args:
x: 声学信号 (B, signal_length)
Returns:
encoded_features: (B, 256, T, 1)
"""
# 多分辨率STFT
short_spec = self.compute_stft(x, self.short_window, self.short_hop)
long_spec = self.compute_stft(x, self.long_window, self.long_hop)

# 对齐时间维度
min_t = min(short_spec.size(-1), long_spec.size(-1))
short_spec = short_spec[..., :min_t]
long_spec = long_spec[..., :min_t]

# CNN特征提取
short_feat = self.short_cnn(short_spec) # (B, 256, F', T)
long_feat = self.long_cnn(long_spec)

# 自适应池化到相同空间维度
short_feat = F.adaptive_avg_pool2d(short_feat, (8, min_t))
long_feat = F.adaptive_avg_pool2d(long_feat, (8, min_t))

# 融合
combined = torch.cat([short_feat, long_feat], dim=1)
fused = self.fusion(combined)

return fused # (B, 256, 8, T)


class TemporalPoseDecoder(nn.Module):
"""
时序姿态解码器

论文Section 3.3实现
使用注意力机制分离多人信息

关键设计:
- 每人每帧分配独立query
- 时空注意力建模人体内时序动态
- 交叉注意力建模人体间依赖
"""

def __init__(self, d_model=256, n_persons=3, n_joints=17,
n_heads=8, n_layers=3, seq_len=5):
super().__init__()
self.n_persons = n_persons
self.n_joints = n_joints
self.seq_len = seq_len # 时序窗口帧数
self.d_model = d_model

# 每人每帧的learnable query
# Shape: (n_persons * seq_len, d_model)
self.person_queries = nn.Parameter(
torch.randn(n_persons * seq_len, d_model) * 0.02
)

# 位置编码
self.pos_encoding = nn.Parameter(
torch.randn(1, n_persons * seq_len, d_model) * 0.02
)

# Transformer解码层
decoder_layer = nn.TransformerDecoderLayer(
d_model=d_model,
nhead=n_heads,
dim_feedforward=d_model * 4,
dropout=0.1,
batch_first=True
)
self.decoder = nn.TransformerDecoder(decoder_layer, num_layers=n_layers)

# 输出头: 3D关节坐标
self.pose_head = nn.Linear(d_model, n_joints * 3)

# 置信度预测
self.confidence_head = nn.Linear(d_model, n_joints)

def forward(self, memory):
"""
Args:
memory: 编码器输出 (B, S, d_model)
S = spatial_dim * temporal_dim
Returns:
poses: (B, n_persons, n_joints, 3)
confidences: (B, n_persons, n_joints)
"""
B = memory.size(0)

# 扩展query到batch维度
queries = self.person_queries.unsqueeze(0).expand(B, -1, -1)
queries = queries + self.pos_encoding

# Transformer解码
decoded = self.decoder(
tgt=queries, # (B, P*T, d_model)
memory=memory # (B, S, d_model)
) # (B, P*T, d_model)

# Reshape: (B, P*T, d_model) -> (B, P, T, d_model)
decoded = decoded.view(B, self.n_persons, self.seq_len, -1)

# 取中间帧的输出作为当前帧姿态
current = decoded[:, :, self.seq_len // 2, :] # (B, P, d_model)

# 预测3D姿态
poses = self.pose_head(current) # (B, P, n_joints*3)
poses = poses.view(B, self.n_persons, self.n_joints, 3)

# 预测置信度
confidences = torch.sigmoid(
self.confidence_head(current)
) # (B, P, n_joints)

return poses, confidences


class SoundMHPE(nn.Module):
"""SoundMHPE: 完整的声学多人姿态估计模型"""

def __init__(self, signal_length=16000, n_persons=3,
n_joints=17, seq_len=5):
super().__init__()
self.encoder = AcousticMultiScaleEncoder(signal_length)
self.decoder = TemporalPoseDecoder(
d_model=256,
n_persons=n_persons,
n_joints=n_joints,
seq_len=seq_len
)

def forward(self, x):
"""
Args:
x: 声学信号 (B, signal_length)
Returns:
poses: (B, n_persons, n_joints, 3)
confidences: (B, n_persons, n_joints)
"""
# 编码
features = self.encoder(x) # (B, 256, 8, T)
B, C, H, T = features.shape

# 展平为序列
memory = features.permute(0, 3, 1, 2) # (B, T, C, H)
memory = memory.reshape(B, T, C * H) # (B, T, 2048)

# 如果维度不匹配,添加投影
if memory.size(-1) != 256:
memory = nn.Linear(memory.size(-1), 256).to(memory.device)(memory)

# 解码
poses, confidences = self.decoder(memory)

return poses, confidences


# 测试代码
if __name__ == "__main__":
# 模拟参数
batch_size = 4
signal_length = 16000 # 1秒 @ 16kHz
n_persons = 3
n_joints = 17

# 创建模型
model = SoundMHPE(
signal_length=signal_length,
n_persons=n_persons,
n_joints=n_joints
)

# 模拟声学输入
x = torch.randn(batch_size, signal_length)

# 前向传播
poses, confs = model(x)

print(f"输入信号: {x.shape}")
print(f"输出姿态: {poses.shape}") # (4, 3, 17, 3)
print(f"置信度: {confs.shape}") # (4, 3, 17)
print(f"参数量: {sum(p.numel() for p in model.parameters()) / 1e6:.2f}M")

# 计算MPJPE
# 假设ground truth
gt_poses = torch.randn(batch_size, n_persons, n_joints, 3)
mpjpe = torch.mean(torch.norm(poses - gt_poses, dim=-1)) # mm
print(f"模拟MPJPE: {mpjpe:.1f} mm (论文报告: 106.5 mm)")

3. AMP 数据集

属性 数值
总时长 6 小时
帧数 432K 同步帧
最大人数 3 人
关节数 17 (SMPL格式)
采样率 16 kHz
场景 室内多场景

4. 实验结果

方法 MPJPE (mm) ↓ PA-MPJPE (mm) ↓
Single-person baseline 128.3 105.7
Naive multi-person extension 119.8 98.4
SoundMHPE (本文) 106.5 87.2
Oracle (上限) 52.1 43.8

消融实验关键发现:

配置 MPJPE (mm)
w/o Multi-scale Encoder 113.2
w/o Temporal Pose Decoder 112.7
w/o 时空query 110.1
完整模型 106.5

IMS OOP 检测应用启示

为什么声学姿态估计对 IMS 重要?

Euro NCAP 2026 OOP(Out-of-Position)检测要求系统识别乘员异常坐姿,传统方案依赖摄像头,但存在隐私和遮挡问题。声学方案提供了全新思路:

应用场景映射

OOP 场景 声学特征 检测可行性
前倾(够东西) 上半身反射路径缩短 ✅ 高
后仰(睡觉) 胸腔反射角度变化 ✅ 高
侧倾(靠着睡) 左右反射不对称 ✅ 中
脚搭仪表台 腿部反射路径变化 ⚠️ 中(距离远)
儿童坐姿不正 体型小、反射弱 ⚠️ 需优化
跪姿/蹲姿 整体高度变化 ✅ 高

IMS 集成架构

多传感器融合方案

声学方案不应替代现有传感器,而是作为融合层补充:

传感器 角色 精度 隐私 成本
RGB/IR 摄像头 主感知 高 ❌ 中
UWB 雷达 CPD/生命体征 中 ✅ 低
座椅压力 乘员分类 中 ✅ 低
声学传感器 OOP姿态补充 中 ✅ 极低(复用扬声器)

硬件需求

组件 型号 参数 说明
扬声器 车载音响系统 20Hz-20kHz 复用现有硬件
超声扬声器 压电陶瓷 18-22kHz, >100dB 定向发射超声
麦克风 驻极体/ MEMS 20Hz-22kHz, SNR>60dB 车载麦克风阵列
处理器 QCS8255 Hexagon NPU 26TOPS 声学模型<5MB

部署优化建议

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
# 量化压缩方案
import torch.quantization as quant

def optimize_for_edge(model):
"""边缘部署优化"""
# 1. 动态量化(INT8)
quantized = quant.quantize_dynamic(
model,
{nn.Linear, nn.Conv2d},
dtype=quant.qint8
)

# 2. 模型大小对比
original = sum(p.numel() for p in model.parameters()) * 4 # float32
quantized_size = sum(
p.qsize() if hasattr(p, 'qsize') else p.numel() * 4
for p in quantized.parameters()
)

print(f"原始模型: {original / 1e6:.2f} MB")
print(f"量化模型: {quantized_size / 1e6:.2f} MB")
print(f"压缩比: {original / quantized_size:.1f}x")

return quantized

# 3. 实时推理配置
INFERENCE_CONFIG = {
"signal_duration": 0.5, # 0.5秒信号
"sample_rate": 16000, # 16kHz
"buffer_size": 8000, # 0.5s buffer
"inference_interval": 1.0, # 每秒推理一次
"max_persons": 3, # 最多3人
"joints": 17, # 17关节
"device": "npu", # NPU推理
"precision": "int8", # INT8量化
}

IMS 开发优先级建议

优先级 任务 时间 产出
🔴 P0 复现 SoundMHPE 模型 2周 可用 PyTorch 模型
🔴 P0 车载扬声器-麦克风声学测试 1周 信号质量评估报告
🟡 P1 OOP 场景数据采集 2周 5类OOP声学数据集
🟡 P1 车载环境适配训练 1周 车载微调模型
🟢 P2 多传感器融合集成 2周 声学+摄像头融合方案

局限性与挑战

  1. 精度限制 — MPJPE 106.5mm vs 摄像头方案通常 30-50mm,精度差距明显
  2. 环境噪声 — 车辆行驶噪声(发动机、风噪、路噪)会干扰声学信号
  3. 人员数量限制 — 当前最多支持3人,座舱可能需要4-5人
  4. 实时性 — 论文未报告实时推理性能,需验证车载部署帧率
  5. 超声频段 — 18kHz 以上信号对部分人群可闻,可能造成不适
  6. 多径干扰 — 座舱内强反射环境可能加剧多径效应

技术路线展望

总结

SoundMHPE 是一个开创性的工作,首次证明了声学信号可以用于多人3D姿态估计。虽然精度尚未达到摄像头水平,但其隐私保护、无光照依赖、可穿透遮挡三大优势使其成为 IMS OOP 检测的极具潜力的补充方案。

对 IMS 团队的核心启示:

  1. 声学传感器几乎零成本(复用车载扬声器和麦克风)
  2. 可作为摄像头 OOP 检测的冗余/隐私模式方案
  3. 与 UWB 雷达形成互补:UWB 做存在检测+生命体征,声学做姿态估计
  4. 需要重点解决车载环境噪声鲁棒性问题

参考链接: