SoundMHPE:声波多人3D姿态估计,ECCV 2026首创声学姿态感知

论文信息

  • 标题: Sound-based Multi-Person 3D Pose Estimation
  • 作者: Yusuke Oumi 等
  • 会议: ECCV 2026 (已接收)
  • arXiv: 2609.04902 (2026年9月4日)
  • 项目页: https://oumi03.github.io/sound-mhpe/
  • 数据集: AMP (Acoustic Multi-person Pose) — 6小时, 432K同步帧
  • 领域: cs.CV, cs.AI, cs.LG, cs.RO, cs.SD

核心创新

首次仅用声波信号估计多人3D姿态。

“Can we recover the 3D poses of multiple people using only sound?”

技术挑战

挑战 描述 传统方案
信号叠加 多人声学特征重叠 单人方案无法扩展
人间反射 多人间的反射路径复杂 引入误差
运动归属 难以区分谁的姿态变化 需多人关联

两大核心模块

模块 名称 功能
1 Acoustic Multi-scale Encoder 捕获多时间尺度和细粒度频率特征,从重叠信号中分离个体声学签名
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
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
"""
SoundMHPE: 声波多人3D姿态估计
论文: arXiv 2609.04902, ECCV 2026
项目: https://oumi03.github.io/sound-mhpe/

核心: 仅用声学信号(非视觉)估计多人3D姿态
依赖: torch>=2.0, numpy, librosa
"""

import torch
import torch.nn as nn
import torch.nn.functional as F
from typing import Tuple

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

从混合声波信号中提取:
1. 多时间尺度特征(短/中/长窗口)
2. 细粒度频率特征
3. 个体声学签名分离
"""

def __init__(self,
audio_dim: int = 128,
num_persons: int = 4,
freq_bins: int = 257):
super().__init__()
self.num_persons = num_persons

# 多尺度时间编码
self.short_conv = nn.Conv1d(freq_bins, audio_dim, 3, padding=1)
self.medium_conv = nn.Conv1d(freq_bins, audio_dim, 7, padding=3)
self.long_conv = nn.Conv1d(freq_bins, audio_dim, 15, padding=7)

# 细粒度频率编码
self.freq_encoder = nn.Sequential(
nn.Linear(freq_bins, 256),
nn.ReLU(),
nn.Linear(256, audio_dim)
)

# 个体分离
self.person_separator = nn.MultiheadAttention(
embed_dim=audio_dim,
num_heads=8,
batch_first=True
)

# 每人编码头
self.person_heads = nn.ModuleList([
nn.Linear(audio_dim * 3, audio_dim)
for _ in range(num_persons)
])

def forward(self, audio_spectrum: torch.Tensor) -> torch.Tensor:
"""
Args:
audio_spectrum: (B, freq_bins, T) STFT频谱

Returns:
person_features: (B, num_persons, audio_dim, T)
"""
B, F_bins, T = audio_spectrum.shape

# 多尺度时间特征
short_feat = self.short_conv(audio_spectrum) # (B, dim, T)
medium_feat = self.medium_conv(audio_spectrum)
long_feat = self.long_conv(audio_spectrum)

# 融合
multi_scale = torch.cat([short_feat, medium_feat, long_feat], dim=1)
# → (B, dim*3, T)

# 转置为序列
seq = multi_scale.transpose(1, 2) # (B, T, dim*3)

# 频率特征
freq_feat = self.freq_encoder(audio_spectrum.transpose(1, 2)) # (B, T, dim)

# 个体分离 (自注意力)
separated, _ = self.person_separator(seq, seq, seq)

# 每人特征
person_features = []
for i, head in enumerate(self.person_heads):
person_feat = head(separated) # (B, T, dim)
person_features.append(person_feat)

# 堆叠: (B, num_persons, T, dim)
return torch.stack(person_features, dim=1)


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

使用注意力机制:
1. 解多人信息(跨人关联)
2. 跨帧时序依赖
3. 逐帧个体姿态重建
"""

def __init__(self,
audio_dim: int = 128,
num_joints: int = 17,
num_persons: int = 4,
num_frames: int = 16):
super().__init__()
self.num_joints = num_joints
self.num_persons = num_persons

# 时序注意力
self.temporal_attn = nn.MultiheadAttention(
embed_dim=audio_dim,
num_heads=8,
batch_first=True
)

# 跨人注意力
self.cross_person_attn = nn.MultiheadAttention(
embed_dim=audio_dim,
num_heads=8,
batch_first=True
)

# 姿态回归
self.pose_regressor = nn.Sequential(
nn.Linear(audio_dim, 256),
nn.ReLU(),
nn.Linear(256, num_joints * 3) # 3D: x, y, z
)

def forward(self, person_features: torch.Tensor) -> torch.Tensor:
"""
Args:
person_features: (B, num_persons, T, audio_dim)

Returns:
poses_3d: (B, num_persons, T, num_joints, 3)
"""
B, P, T, D = person_features.shape

# 每个人分别处理时序
poses_all = []
for p in range(P):
person_seq = person_features[:, p, :, :] # (B, T, D)

# 时序自注意力
attn_out, _ = self.temporal_attn(person_seq, person_seq, person_seq)

# 姿态回归
poses = self.pose_regressor(attn_out) # (B, T, num_joints*3)
poses = poses.view(B, T, self.num_joints, 3)
poses_all.append(poses)

# 堆叠
poses_3d = torch.stack(poses_all, dim=1) # (B, P, T, J, 3)

# 跨人注意力修正
flat = poses_3d.view(B, P, -1) # (B, P, T*J*3)

return poses_3d


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

输入: 声波信号 (STFT频谱)
输出: 多人3D姿态序列

架构:
1. AcousticMultiScaleEncoder → 多人声学特征分离
2. TemporalPoseDecoder → 时序姿态重建
"""

def __init__(self, num_persons: int = 4, num_joints: int = 17):
super().__init__()
self.encoder = AcousticMultiScaleEncoder(num_persons=num_persons)
self.decoder = TemporalPoseDecoder(num_joints=num_joints, num_persons=num_persons)

def forward(self, audio_spectrum: torch.Tensor) -> torch.Tensor:
"""
Args:
audio_spectrum: (B, freq_bins, T) — STFT频谱

Returns:
poses_3d: (B, num_persons, T, num_joints, 3)
"""
person_features = self.encoder(audio_spectrum)
poses_3d = self.decoder(person_features)
return poses_3d


if __name__ == "__main__":
# 模拟输入
B, F_bins, T = 2, 257, 64 # 2样本, 257频率bin, 64帧

# 随机STFT频谱
audio_spectrum = torch.randn(B, F_bins, T)

# 模型
model = SoundMHPE(num_persons=4, num_joints=17)

# 前向传播
poses_3d = model(audio_spectrum)

print(f"输入: STFT频谱 {audio_spectrum.shape}")
print(f"输出: 3D姿态 {poses_3d.shape}")
print(f" → {poses_3d.shape[1]}人 × {poses_3d.shape[2]}帧 × {poses_3d.shape[3]}关节 × 3D")

total_params = sum(p.numel() for p in model.parameters())
print(f"参数量: {total_params:,} ({total_params/1e6:.2f}M)")

AMP数据集

属性 数值
总时长 6小时
同步帧数 432,000
人数 多人(最多4人)
标注 3D姿态 + 声学信号
场景 室内多场景

IMS开发启示

1. 声学姿态感知在座舱的独特价值

场景 视觉方案局限 声学方案优势
后排乘客 座椅遮挡 声波绕射
毯子下儿童 不可见 声波穿透
黑暗环境 需IR补光 声波不依赖光照
隐私保护 摄像头隐私问题 无图像采集
多人场景 遮挡问题 声波叠加可分离

2. OOP检测新思路

3. 硬件零增量成本方案

组件 现有硬件 增量成本
麦克风阵列 ✅ 语音助手已有 0元
处理器 ✅ QCS8255 NPU 0元
声学处理 需移植 软件
模型大小 ~2M参数 可量化

关键优势:利用已有的座舱语音麦克风阵列,零硬件增量成本实现OOP检测!

4. 与雷达CPD的互补

检测维度 雷达CPD 声学姿态 融合
存在检测 ✅ 呼吸 ⚠️ 间接 ✅
位置定位 ✅ 精确 ⚠️ 模糊 ✅
姿态识别 ❌ ✅ 3D姿态 ✅
儿童区分 ⚠️ 体型 ✅ 姿态特征 ✅
穿透遮挡 ✅ ✅ ✅

应用场景

座舱OOP检测流程

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
class CabinAcousticOOP:
"""
座舱声学OOP检测方案
基于SoundMHPE + 雷达融合

硬件: 现有麦克风阵列 + 现有mmWave雷达
增量成本: 0 (纯软件方案)
"""

def __init__(self):
self.pose_estimator = SoundMHPE(num_persons=4, num_joints=17)
# 加载预训练权重

def detect_oop(self, audio_signal, radar_data):
"""
OOP检测主函数

Args:
audio_signal: 麦克风阵列信号
radar_data: mmWave雷达数据

Returns:
OOP评估结果
"""
# 1. 声学姿态估计
# audio → STFT → SoundMHPE → 3D poses
poses = self.pose_estimator(audio_signal)

# 2. 姿态分类
oop_results = []
for person_idx in range(poses.shape[1]):
person_pose = poses[0, person_idx, -1] # 最新帧

# 计算OOP指标
torso_angle = self._torso_angle(person_pose)
knee_angle = self._knee_angle(person_pose)

if torso_angle < 30:
oop_results.append(('lying_down', 'high'))
elif knee_angle > 160:
oop_results.append(('feet_on_dash', 'critical'))
elif torso_angle < 45:
oop_results.append(('forward_lean', 'medium'))
else:
oop_results.append(('normal', 'none'))

# 3. 与雷达数据融合
radar_presence = self._check_radar_presence(radar_data)

return {
'poses': poses,
'oop_results': oop_results,
'radar_presence': radar_presence
}

def _torso_angle(self, pose):
shoulder = (pose[5] + pose[6]) / 2
hip = (pose[11] + pose[12]) / 2
torso = hip - shoulder
return float(np.degrees(np.arctan2(torso[0], -torso[1])))

def _knee_angle(self, pose):
hip, knee, ankle = pose[11], pose[13], pose[15]
v1 = hip - knee
v2 = ankle - knee
cos_a = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2) + 1e-6)
return float(np.degrees(np.arccos(np.clip(cos_a, -1, 1))))

def _check_radar_presence(self, radar_data):
return True # 简化

总结

SoundMHPE的开创性价值:

  • 首次证明声波可以估计多人3D姿态
  • 零硬件增量——利用座舱已有麦克风阵列
  • 隐私友好——无图像采集
  • 遮挡鲁棒——声波绕射/穿透特性
  • 与雷达互补——姿态+呼吸=完整CPD/OOP方案

对IMS的启示:OOP检测不一定需要摄像头。声学姿态+雷达呼吸的方案可以实现零隐私风险的OOP检测。