PartCrafter

PartCrafter:一张图,生成多个能拼在一起的零件

输入一张参考图和零件数 \(k\),模型同时生成 \(k\) 个独立 mesh。核心做法是:每个零件用一组 token 表示,各组一边完善自己的形状,一边协调彼此的位置。

下面用一张桌子图片讲解:指定 \(k=5\),希望得到一个桌面和四条桌腿。这是教学示例,模型输入里没有这五个零件的名称。

1. 从参考图到 mesh,怎么走

flowchart TD Image[参考图] --> Features[DINOv2 提取图像特征] Count[指定零件数 k] --> Noise[随机采样 k 组噪声 token] Features --> Denoise[联合去噪:反复更新所有组] Noise --> Denoise Denoise --> VecSet[每个零件得到一组 VecSet] VecSet --> SDF[逐组解码并查询 SDF] SDF --> MC[Marching Cubes 提取表面] MC --> Mesh[k 个独立 mesh]

图像告诉模型“想生成什么样的物体”,\(k\) 决定准备多少组表示。去噪结束后,每组分别转成一个网格。

VecSet 可以理解成描述形状的一组向量。它是压缩的几何信息,还不是顶点和三角形。PartCrafter 沿用 TripoSG 的 3D 编码器、解码器和预训练生成能力,在这个基础上学习多个零件如何共同生成。

2. 最主要的设计:分组表示,交替交流

每个零件有自己的 token 组

如果输入 \(k=5\),就采样五组独立高斯噪声。每组有 \(T\) 个 token,每个 token 有 \(C\) 个数,合起来是:

\[\mathbf Z\in\mathbb R^{k\times T\times C}. \]

模型在整个去噪过程中保留这五组边界,最后每组单独解码。因此,输出天然是五份可独立操作的几何。

网络还给每组加上不同的身份向量,区分“这是谁的 token”。它只是编号,不表示“第 1 组必须是桌面”。训练会打乱零件顺序,避免编号固定绑定某种零件。

局部注意力:把自己的形状做好

每组内部的 token 互相交流。

例如,一条桌腿的各个位置需要协调粗细、长度和表面形状,这些信息由本组的局部注意力处理。

全局注意力:让各个零件配合起来

把所有组的 token 拼起来做注意力,让不同零件也能互相读取信息,再拆回原来的组。

例如,桌腿需要结合桌面的大小和位置,生成合适的长度与摆放位置;不同组也需要学会分工,减少重复生成同一块几何。

网络在不同层交替使用全局、局部注意力。两类层都通过交叉注意力读取同一张完整参考图的特征,所以各组都能根据图片调整自己,无需提前把图片切成五块。

一次去噪网络前向:
    给各组加入身份和当前噪声阶段的信息
    逐层处理:
        全局层:所有零件的 token 一起交流
        局部层:每个零件只在自己的组内交流
        读取参考图特征,调整当前形状
    输出每组 token 的更新方向

这里既要保持“每组负责一个零件”,又要允许“不同零件互相影响”。这两件事结合起来,才容易生成组成完整物体的部件。

3. 怎么训练:用真实零件教模型去噪

训练样本包含一张图片,以及对应的、已经有零件划分的 3D 物体。很多原始 3D 资产本来就由艺术家分组件制作,方法利用了这些信息。

以五零件桌子为例,先把桌面和四条桌腿分别编码成五组干净 VecSet,再混入噪声:

\[\mathbf Z_\sigma =(1-\sigma)\mathbf Z_{\rm clean}+\sigma\boldsymbol\epsilon. \]

\(\mathbf Z_{\rm clean}\) 是真实零件的表示,\(\boldsymbol\epsilon\) 是随机噪声,\(\sigma\) 是噪声比例:\(\sigma=1\) 是纯噪声,\(\sigma=0\) 是干净表示。

Flow matching 在这里就是教网络预测“接下来往哪个方向改”。按去噪方向来写,目标是 \(\mathbf Z_{\rm clean}-\boldsymbol\epsilon\);训练让预测方向与这个目标的均方误差尽量小。

flowchart TD Parts[真实零件集合] --> VAE[每个零件分别编码] VAE --> Clean[干净 VecSet] Clean --> Mix[与高斯噪声混合] Mix --> Network[参考图引导的联合去噪网络] Network --> Prediction[预测更新方向] Clean --> Target[干净 VecSet 减去噪声] Prediction --> Loss[比较两个方向并训练网络] Target --> Loss

同一物体的所有零件共享噪声比例,但各组的噪声不同。这样,五个零件处在同一个生成阶段,可以同步协调。公开训练流程冻结 3D VAE 和图像编码器,主要训练去噪网络及部件身份参数。

五零件物体,会不会也用 \(k=2,3,4\) 训练?

对于已有五零件标注的这个样本,训练就用五组。随机打乱的是顺序,数量不变。官方训练路径没有自动把它合并或抽成两、三、四组。

模型能处理不同 \(k\),是因为训练集本身就包含不同零件数的样本:

教学样本 训练时的零件数
桌面与四条桌腿 \(k=5\)
灯罩、灯杆、底座 \(k=3\)
作为整体表示的物体 \(k=1\)

这些样本训练的是同一个模型。

推理时可以对同一张桌子图尝试 \(k=2\)\(k=5\),模型会根据组数重新分配几何。但训练并没有教过每个物体的所有拆分粒度,所以不能保证 \(k=2\) 一定得到“桌面”和“四条腿的合体”。

4. 怎么生成:从噪声走到零件,再提取表面

推理时没有真实 mesh,直接从 \(k\) 组噪声开始。在每个时间步,网络看当前所有组和参考图,预测更新方向,然后所有组一起前进一步。

若噪声比例从 \(\sigma\) 降到更小的 \(\sigma'\),更新就是:

\[\mathbf Z_{\rm next} =\mathbf Z+(\sigma-\sigma')\,\mathbf u_\theta. \]

\(\mathbf u_\theta\) 是预测的去噪方向。不断重复,直到噪声比例降到零,得到每个零件的 VecSet。实际推理还可以加强图像条件的引导;这里保留主流程。

接下来,每组使用同一个几何解码器:

零件 VecSet + 查询点坐标 → 这个点的 SDF 值。

SDF 表示点离表面多远,并用正负区分内外。查询一批三维空间坐标后,Marching Cubes 找到 SDF 为零的表面,并把它连成三角网格。

图像特征 ← 编码参考图
当前表示 ← 采样 k 组高斯噪声

反复执行直到噪声比例降到零:
    更新方向 ← 联合去噪网络(所有组、当前噪声比例、图像特征)
    当前表示 ← 当前表示 + 步长 × 更新方向    # 所有零件同步更新

对每组最终 VecSet:
    距离场 ← 共享解码器(VecSet、空间查询坐标)
    零件 mesh ← Marching Cubes(距离场的零等值面)

零件解码后已经带有相对位置。训练时对整个物体统一归一化,所有零件保留在共同坐标系中,没有把每个零件单独移到原点。所以桌腿的表示同时包含它的形状和位置,不需要另一个装配模块再把它放到桌面下面。

5. 理解到这里,还需记住三个边界

  • 控制数量,不直接控制语义。输入 \(k=5\) 不能保证第几组对应哪个指定零件。
  • 隐藏结构靠学到的经验补全。看不到的桌腿可以生成出来,但不保证和实物完全一致。
  • 可拆分不等于机械可装配。核心输出是几何,不自带关节,也没有硬性保证部件无穿插、接触严密。

论文 · 官方代码

posted @ 2026-09-08 16:26  S-X-Q  阅读(7)  评论(0)    收藏  举报