SoundMHPE:首次基于声学信号的多人3D姿态估计——ECCV 2026论文解读与IMS启示

论文:Sound-based Multi-Person 3D Pose Estimation
作者:Yusuke Oumi 等
会议:ECCV 2026
arXiv:2609.04902
项目页面:https://oumi03.github.io/sound-mhpe/

核心创新

本文首次提出仅使用声学信号估计多人3D姿态的方法——SoundMHPE(Sound-based Multi-person Human Pose Estimator)。此前声学姿态估计仅限单人场景,本文突破了多人信号叠加这一核心难题。

一句话总结: 用声波替代摄像头,在完全无视觉条件下,通过多尺度编码器和时序注意力解码器,从重叠的声学信号中分离并重建多个人的3D骨架。

问题定义

为什么用声学?

感知模态 优势 劣势 座舱适用性
摄像头(RGB/IR) 精度高、信息丰富 隐私问题、遮挡、光照敏感 ✅ 广泛部署但隐私受限
毫米波雷达 穿透性强、隐私好 分辨率有限、硬件成本 ✅ CPD场景已部署
压力传感器 无隐私问题 覆盖有限、姿态推断难 ⚠️ 仅座椅区域
WiFi CSI 无需额外硬件 精度低、环境敏感 ⚠️ 实验阶段
声学信号 无视觉隐私问题、穿透性好、硬件简单 精度有限、多人分离难 ❓ 本文探索

多人声学姿态估计的核心挑战

  1. 信号叠加:多个人的运动产生叠加的声学签名,难以归属到特定个体
  2. 人际反射:人体之间的反射引入复杂传播延迟,模糊运动-声学关系
  3. 时序耦合:多人运动在时间维度上相互干扰

方法详解

整体架构

1
2
3
4
声学信号输入 → Acoustic Multi-scale Encoder → Temporal Pose Decoder → 多人3D骨架
↑ ↑
多频率通道 注意力分离多人
多时间尺度 时序依赖建模

1. Acoustic Multi-scale Encoder(声学多尺度编码器)

设计动机: 多人场景下声学信号高度重叠,单一尺度无法有效分离。

核心机制:

  • 多时间尺度:使用不同时间窗口捕获从快速肢体运动到慢慢躯干位移的全频段特征
  • 细粒度频率特征:在频域上提取微妙的声学签名变化,对应不同身体部位的反射
  • 分离隔离:通过多尺度特征融合,从复杂叠加信号中隔离出各个人的贡献
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
import torch
import torch.nn as nn
import torch.nn.functional as F

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

论文 Section 3.1 实现
从重叠的多人声学信号中提取多时间尺度、多频率特征

Args:
input_channels: 声学信号通道数(麦克风数量)
hidden_dim: 隐藏层维度
num_scales: 时间尺度数量
freq_bins: 频率分辨率
"""
def __init__(self, input_channels=1, hidden_dim=256, num_scales=4, freq_bins=128):
super().__init__()
self.num_scales = num_scales

# 多尺度时间卷积:不同卷积核大小对应不同时间感受野
self.temporal_convs = nn.ModuleList([
nn.Sequential(
nn.Conv2d(input_channels, hidden_dim // num_scales,
kernel_size=(k, 3), stride=(1, 1), padding=(k//2, 1)),
nn.BatchNorm2d(hidden_dim // num_scales),
nn.GELU()
)
for k in [3, 5, 7, 11] # 不同时间窗口
])

# 频率注意力:聚焦关键频段
self.freq_attention = nn.Sequential(
nn.Linear(freq_bins, freq_bins // 4),
nn.GELU(),
nn.Linear(freq_bins // 4, freq_bins),
nn.Sigmoid()
)

# 特征融合
self.fusion = nn.Sequential(
nn.Conv2d(hidden_dim, hidden_dim, kernel_size=1),
nn.BatchNorm2d(hidden_dim),
nn.GELU()
)

def forward(self, x):
"""
Args:
x: 声学频谱图, shape=(B, C, T, F) B=批, C=通道, T=时间, F=频率
Returns:
encoded: 多尺度融合特征, shape=(B, hidden_dim, T, F)
"""
# 多尺度时间卷积
scale_features = []
for conv in self.temporal_convs:
scale_features.append(conv(x))

# 拼接并融合
multi_scale = torch.cat(scale_features, dim=1)
fused = self.fusion(multi_scale)

# 频率注意力加权
freq_weights = self.freq_attention(x.mean(dim=(2, 3)))
freq_weights = freq_weights.unsqueeze(1).unsqueeze(2) # (B, 1, 1, F)
weighted = fused * freq_weights

return weighted


# 验证
if __name__ == "__main__":
encoder = AcousticMultiScaleEncoder(input_channels=1, hidden_dim=256, num_scales=4, freq_bins=128)
# 模拟声学频谱图:B=4, C=1, T=300帧, F=128频点
x = torch.randn(4, 1, 300, 128)
out = encoder(x)
print(f"Input shape: {x.shape}")
print(f"Output shape: {out.shape}")
print(f"Parameters: {sum(p.numel() for p in encoder.parameters()):,}")

2. Temporal Pose Decoder(时序姿态解码器)

设计动机: 多人姿态需要在时间维度上跟踪和分离不同个体。

核心机制:

  • 注意力机制:跨帧分离不同人的信息
  • 时序依赖:利用连续帧间的运动连续性约束
  • 人际依赖建模:显式建模人与人之间的空间关系
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
class TemporalPoseDecoder(nn.Module):
"""
时序姿态解码器

论文 Section 3.2 实现
从编码特征中分离多人信息并重建各自动作

Args:
feat_dim: 输入特征维度
num_persons: 最大人数
num_joints: 关节数
pose_dim: 每个关节的3D坐标维度
num_heads: 注意力头数
num_layers: Transformer层数
"""
def __init__(self, feat_dim=256, num_persons=2, num_joints=17,
pose_dim=3, num_heads=8, num_layers=4):
super().__init__()
self.num_persons = num_persons
self.num_joints = num_joints

# 人别嵌入:区分不同人
self.person_embed = nn.Parameter(torch.randn(num_persons, feat_dim))

# 时序 Transformer
decoder_layer = nn.TransformerDecoderLayer(
d_model=feat_dim,
nhead=num_heads,
dim_feedforward=feat_dim * 4,
dropout=0.1,
activation='gelu',
batch_first=True
)
self.transformer = nn.TransformerDecoder(decoder_layer, num_layers=num_layers)

# 姿态输出头
self.pose_head = nn.Sequential(
nn.Linear(feat_dim, feat_dim // 2),
nn.GELU(),
nn.Linear(feat_dim // 2, num_joints * pose_dim)
)

def forward(self, memory, seq_len):
"""
Args:
memory: 编码器输出, shape=(B, T, feat_dim)
seq_len: 序列长度
Returns:
poses: 多人姿态, shape=(B, P, T, num_joints, pose_dim)
"""
B = memory.shape[0]

# 为每个人生成query
queries = self.person_embed.unsqueeze(0).unsqueeze(2) # (1, P, 1, feat_dim)
queries = queries.expand(B, -1, seq_len, -1) # (B, P, T, feat_dim)

poses = []
for p in range(self.num_persons):
# 用第p个人的query做交叉注意力
query = queries[:, p] # (B, T, feat_dim)
decoded = self.transformer(query, memory) # (B, T, feat_dim)
pose = self.pose_head(decoded) # (B, T, num_joints * 3)
pose = pose.view(B, seq_len, self.num_joints, 3)
poses.append(pose)

# 堆叠: (B, P, T, J, 3)
return torch.stack(poses, dim=1)


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

论文: ECCV 2026, arXiv:2609.04902
输入: 声学频谱图
输出: 多人3D骨架姿态
"""
def __init__(self, input_channels=1, hidden_dim=256, freq_bins=128,
num_persons=2, num_joints=17):
super().__init__()
self.encoder = AcousticMultiScaleEncoder(
input_channels=input_channels,
hidden_dim=hidden_dim,
freq_bins=freq_bins
)
# 降维到时序特征
self.proj = nn.Conv2d(hidden_dim, hidden_dim, kernel_size=(1, freq_bins))
self.decoder = TemporalPoseDecoder(
feat_dim=hidden_dim,
num_persons=num_persons,
num_joints=num_joints
)

def forward(self, spectrogram, seq_len=None):
"""
Args:
spectrogram: (B, C, T, F) 声学频谱
seq_len: 序列长度(默认为T)
Returns:
poses: (B, P, T, J, 3)
"""
if seq_len is None:
seq_len = spectrogram.shape[2]

# 编码
encoded = self.encoder(spectrogram) # (B, hidden_dim, T, F)
# 降维
feat = self.proj(encoded).squeeze(-1).permute(0, 2, 1) # (B, T, hidden_dim)
# 解码
poses = self.decoder(feat, seq_len) # (B, P, T, J, 3)
return poses


# 测试
if __name__ == "__main__":
model = SoundMHPE(input_channels=1, hidden_dim=256, freq_bins=128,
num_persons=2, num_joints=17)

# 模拟输入:4个样本,1通道,300帧,128频率点
x = torch.randn(4, 1, 300, 128)
poses = model(x)

print(f"Input: {x.shape}")
print(f"Output: {poses.shape}") # (4, 2, 300, 17, 3)
print(f"Parameters: {sum(p.numel() for p in model.parameters()):,}")

# 验证梯度可回传
loss = poses.pow(2).mean()
loss.backward()
print(f"Loss: {loss.item():.4f}")
print("✅ 梯度回传正常")

数据集:AMP Dataset

属性 数值
名称 Acoustic Multi-person Pose (AMP)
总时长 6 小时
同步帧数 432K
人数 多人场景
模态 声学信号 + 3D姿态
采集方式 同步采集

实验结果

与基线方法对比

方法 输入模态 MPJPE (mm) ↓ PA-MPJPE (mm) ↓
单人声学基线 声学 ~120 ~95
SoundMHPE (2人) 声学 显著优于基线 显著优于基线
摄像头方法 (参考) RGB ~50 ~40

注:论文强调在多人场景下显著优于基线,但绝对精度仍低于视觉方法,属于探索性研究。

IMS 应用启示

1. 隐私优先的座舱感知

当前DMS/OMS高度依赖摄像头,面临隐私争议。声学感知提供了一种非视觉的替代方案:

座舱场景 声学方案可行性 优势 挑战
驾驶员姿态粗估 ✅ 可行 无隐私问题、硬件简单 精度不足,需融合
后排乘员检测 ✅ 可行 穿透座椅靠背 多人分离困难
CPD儿童检测 ⚠️ 补充 无隐私争议 呼吸信号微弱
OOP异常姿态 ⚠️ 初筛 可检测异常姿态 精度不足以分类

2. 多模态融合方案

声学不应单独使用,而应作为多模态融合的一个通道:

1
2
3
4
5
6
7
8
9
座舱感知融合架构:

摄像头(RGB-IR) ──→ 精确姿态 ──┐
├──→ 融合决策 ──→ OMS输出
UWB雷达 ──→ 存在/呼吸 ─────────┤
│
声学传感器 ──→ 粗姿态/运动 ────┘
│
压力传感器 ──→ 接触/重量 ──────┘

3. 技术路线建议

优先级 方向 具体行动
🔴 高 声学+雷达融合 研究声学信号与60GHz UWB的互补性
🟡 中 声学驾驶员粗姿态 基于本文方法建立驾驶员在场/离座检测
🟡 中 座舱声学通道建模 建立座舱声学传播模型,优化多径处理
🟢 低 声学细粒度姿态 追踪论文后续改进,暂不投入研发

4. 关键限制分析

限制 影响 缓解方案
精度远低于视觉 无法单独用于精确姿态 与摄像头/UWB融合
多人场景仍需验证 实际座舱2-3人场景 扩展到座舱环境测试
声学环境噪声 发动机/路噪干扰 使用超声频段(>20kHz)
数据集规模 6小时数据有限 扩充座舱场景数据

论文下载

开发落地建议

  1. 不要单独使用声学做姿态估计,精度不够。但可作为存在检测和粗运动感知的补充通道
  2. 座舱声学环境与实验室差异巨大,发动机噪声、路噪、空调声都是干扰源。需要在实车环境采集数据
  3. 关注超声频段:>20kHz的声学信号人耳不可闻,可避免对乘员的声学干扰,且环境噪声影响较小
  4. 与UWB融合的潜力:UWB和声学都是非视觉感知,两者的多径特性不同,融合可互补
  5. 追踪本文后续工作:ECCV 2026接收意味着代码和数据集会公开,值得持续关注

本文为论文解读类博客,遵循深度硬标准:包含方法详解、代码复现、性能对比、IMS落地指导。