PartPacker 方法讲解
PartPacker 方法讲解
论文:Efficient Part-level 3D Object Generation via Dual Volume Packing
代码:NVlabs/PartPacker
1. 一句话理解
PartPacker 不直接为每个部件生成一个 3D latent,而是把所有部件分到两个体积中:
同一体积中的部件不能互相接触,因此解码后可以按连通组件自动拆开。
2. 它要解决什么问题?
普通 image-to-3D 方法通常输出一个融合网格:
椅子 = 椅面 + 椅腿 + 靠背
这些部分会融合在同一个 mesh 中,难以单独编辑。直接为每个部件分配一个体积又有两个问题:
- 部件数量可变,网络输出长度难以固定;
- 部件越多,生成计算量越大。
PartPacker 的目标是:
固定生成两个体积
↓
每个体积中可以包含任意数量的独立部件
↓
解码后按连通组件拆出部件
3. 双体积打包
3.1 把部件关系变成图
构造部件接触图 \(G=(V,E)\):
- 顶点 \(V\):3D 部件;
- 边 \(E\):两个部件在空间中接触;
- 相邻顶点不能放入同一个体积。
这等价于图着色问题:
一种合法分配可以是:
Volume 0:椅面
Volume 1:靠背、四条椅腿
只要同一体积中的部件互不接触,解码后的网格就会有多个连通组件。
3.2 非二分图的处理
如果三个部件两两接触,会形成奇环:
这种图不能只用两个颜色表示。PartPacker 使用启发式的奇环收缩:
穿透深度较大的两个部件本来就更容易被视为一个整体,因此优先合并它们。
4. 数据准备
每个体积会被转换成 watertight mesh,并生成:
- 均匀表面点;
- 显著边缘点;
- 点与 SDF 值,用于监督几何重建。
两个体积的占用比例过于不平衡时会被过滤,因为一个几乎为空的体积不利于训练。
5. 网络结构
关键设计:
- 两个 latent 联合去噪:两个体积可以通过 Transformer 交换信息,保持整体结构一致。
- 第二体积使用 part embedding:帮助模型区分 Volume 0 和 Volume 1,避免生成两个相同体积。
- VAE 采用显著边缘采样:加强对尖锐边缘和细节的重建能力。
- Rectified Flow:从随机噪声逐步生成 3D latent,不同随机种子可以得到不同结果。
代码中的默认单体积 latent 大小约为 \(4096 \times 64\),双体积拼接后大致为 \(8192 \times 64\)。
6. 训练流程
微调 VAE 是必要的,因为部件网格可能很小、偏离物体中心,直接使用融合网格 VAE 容易出现伪影。
7. 推理和文件输出
典型输出:
object_0.glb # 所有部件组合后的物体
object_0_vol0.glb # Volume 0
object_0_vol1.glb # Volume 1
object_0_part0.glb # 独立部件 0
object_0_part1.glb # 独立部件 1
object_0_part2.glb # 独立部件 2
因此,每个 *_partN.glb 都是一个独立的 mesh 文件;但模型内部首先生成的是两个包含多个部件的体积。
8. 优点与局限
| 优点 | 局限 |
|---|---|
| 不需要额外的 2D 分割模型 | 部件粒度依赖原始网格标注 |
| 一次生成所有部件 | 不同随机种子可能产生不同划分 |
| 输出部件数量可以变化 | 三个以上部件互相接触时,双体积表达能力不足 |
| 推理时间不随部件数量线性增加 | 奇环收缩可能合并两个语义不同的部件 |
| 输出的是完整 3D 部件,而不是可见表面片段 | 复杂内部结构可能生成错误或缺失 |
9. 最核心的理解
PartPacker 的关键不是“预测一个部件列表”,而是:
部件接触图
↓
二分成两个互不接触的部件集合
↓
联合生成两个 SDF 体积
↓
按连通组件恢复任意数量的部件
也可以概括为:
用固定长度的双体积表示,解决可变数量的部件生成问题。
本文来自博客园,作者:S-X-Q,转载请注明原文链接:https://www.cnblogs.com/sxq-blog/p/23299663

浙公网安备 33010602011771号