Reading Self-supervised Single-view 3D Reconstruction via Semantic Consistency
论文地址:https://arxiv.org/abs/2003.06473
作者:Xueting Li, Sifei Liu, Kihwan Kim, Shalini De Mello, Varun Jampani, Ming-Hsuan Yang, and Jan Kautz
发表: ECCV 2020
链接: https://github.com/NVlabs/UMR
如果你去做这个任务,会怎么做?作者做的方法和你想的有什么差异?
Why:
- 在3d重建模任务中,同时预测形状、相机位置和材质是一个很大的问题,因为它内在的不确定性。
- 现有方法都需要借助各种手段:3D层面的监督、2D语义关键点、shading(这是什么?)、特定类别的3D template 、多视角等等。这些方法需要大量人力,所以很难广泛应用。
- 人类会直觉感知到一个物体包括各个部分,比如鸟有两只腿、两个翅膀、一个头,从而识别物体。类似的,cv受此启发,也可以将一个物体定义为多个可变形的部分的集合。
What:
- 仅需要单张图片+轮廓mask,利用语义一致性,实现自监督3D重建模
- 思路:1. 每个物体可以看作由可变形的部分组成;2. 对同一类型的不同物体,它们的每一部分在语义上都是一致的
- 通过自监督学习大量同类的图片,可以建立重建的mesh模型与图片之间的语义一致性。这样在同时预测形状、相机位置和材质的时候,可以降低模糊性。
- 第一个做到不需要特定类别的template mesh模型或者语义关键点,就可以从单视角图像中实现3d重建模。因此,这个方法可以推广到各种物体类别,而不需要类别的标签
读前疑问:
How:
模型

- (a)是原始图片。需要同一类别的大量图片一起作为输入
- (b)用SCOPS模型(另一篇工作),对图像进行语义分割的结果。这个模型也是自监督的
- (c)标准语义 uv map(Canonical semantic uv map):
- 理论上,同一类物体的mesh模型,尽管各自都有不同的形状,但每个点的语义含义都是一致的。
- 因此,根据前一步生成的大量语义分割结果,可以生成一张对应这个类别的Canonical语义uv map。
- (d)由前一步生成的Canonical语义uv map,可以得到重建的mesh模型表面的点对应的语义标签
- 橘色箭头:这个就是语义一致性了,它鼓励2D图像和3D模型之间的语义标签相互一致。这样,就可以解决前面提到过的在3D重建模的时候的“相机-形状不确定性”这个难题
具体方法
CMR是baseline
- 用三个decoder \(D_{shape}\ D_{camera}\ D_{texture}\) 同时预测mesh模型的形状、相机和材质
- 形状 \(V=\tilde V + \Delta V\),其中 $V $ 是某类物体的template mesh模型,\(\Delta V\) 是预测出来的点的偏移量
- 相机pose \(\theta\) 是 weak perspective transformation (?)
- 材质 \(I_{flow}\) 是 UV flow,是将输入图片到UV空间的映射,然后它可以被一个已经定义好的函数\(\phi\)映射到mesh模型的表面的每一个点
- 但是CMR需要人工标注的关键点作为输入,这篇论文主要就是把它去掉了。去掉之后呢,会出现相机+形状同时预测时Ambiguity的问题,所以就想方设法解决这个问题。

语义一致性:解决相机+形状同时预测时的Ambiguity
也就是Fig 3中红色框的部分。
语义部件不变性 semantic part invariance:
- 对于2D图像,用SCOPS(自监督co-part语义分割,另一篇论文的方法)可以很准确地对物体各个部分进行分割
- 对于3D mesh,每个点的语义含义是固定不变的,就算每个物体会有各自的形变
语义一致性:
从Fig 4 (i) 可以看到,如果没有语义一致性,mesh模型中原本对应头的顶点被当作了翅膀尖,这样错误的变形对应了错误的相机pose。这就是相机+形状同时预测时的Ambiguity。
前面已经提到过,可以为每个具体类别生成一张标准语义 uv map(Canonical semantic uv map)。这里,就可以让 每个物体的2D语义分割结果 与 标准语义 uv map 保持一致性,从而让3D模型的每个语义部件跟2D图像里相应的位置有对应关系。这样可以很好地解决相机-形状Ambiguity问题。
通过SCOPS实现2D图像中部件的分割
SCOPS 是自监督的方法,从一类物体的大量图片中发掘共同的语义部件。Fig 10第二行就是它的结果。后面还会提到,通过本文的方法,还可以反过来提升SCOPS的结果:利用生成的标准语义UV map作为伪标注反过来进行监督。
通过标准语义uv map实现3D模型中部件的分割
已经有了:
- 模型学到的texture flow \(I_{flow}\)可以将输入图片映射到UV空间,然后它可以被一个已经定义好的函数\(\phi\)映射到mesh模型的表面的每一个点
- 通过SCOPS生成的图像 \(i\) 的语义分割结果 \(P^i\in R^{H\times W\times N_p}\), 其中H和W是长和宽, \(N_p\) 是语义部件数量
这样的话,通过模型的 \(I_{flow}\) 就可以把2D的语义分割结果 \(P^i\) 映射到 UV 空间,把这个称为 语义UV map
理论上来说,同一类别的所有物体都应该得到同一个语义UV map,因为 1. 根据语义部件不变性,mesh模型的每个顶点对应的语义部件都是固定不变的 2. UV map和3d mesh 中的点又是通过\(\Phi\)映射的关系,每个顶点对应的UV map上的坐标也是不变的。
但是因为SCOPS + \(I_{flow}\) 的误差,各个物体生成的语义UV map事实上很不一样。所以这里提出了对 标准语义UV map \(\bar P_{uv}\) 的估计方法:
通过某种方法选择出训练集中效果比较好的子集 \(\mathcal{U}\),对它们的结果进行加和,
选择样本的方式:
- 首先选择最好的那一个样本,即 perceptual distance(3D投影到2D的图像与原始RGB图像的知觉距离?)最小的
- 然后选择K个跟这个最好的样本最接近的样本,即它们的语义UV map最接近
公式如下:
\[ \bar P_{uv}=\frac{1}{|\mathcal{U}|}\sum_{i\in \mathcal{U}}I^i_{flow}(P^i) \]
其中 \(I^i_{flow}(P^i)\) 就是通过 \(I_{flow}\) 映射语义分割结果 \(P^i\) 得到的 语义UV map。
2D 和 3D 间的语义一致性
基于概率的约束 Probability-based constraint
\[ L_{sp}=||P^i-\mathcal{R}(\Phi (\bar P_{uv});\theta^i)||^2 \]
标准语义UV map \(\bar P_{uv}\) 由预定义好的函数 \(\Phi\) 映射到 3D mesh表面,然后采用预测好的相机pose \(\theta^i\) ,用可微分渲染 \(\mathcal{R}\) 将3D模型渲染到2D,然后将结果与对应的由SCOPS生成的部件分割概率图 \(P^i\) 做均方误差。
注:这个由SCOPS生成的图像分割结果 \(P^i\) 是概率数值的形式
经验性地选择了采用均方误差MSE,比 KullbackLeibler divergence 效果好
基于顶点的约束 Vertex-based constraint
让3D模型投影回2D之后,被分类到某个语义part的顶点仍然处在图像中该part对应的区域
\[ L_{sv}=\sum^{N_p}_{p=1} \frac{1}{|\bar V_p|}Chamfer(\mathcal{R}(\bar V_p;\theta^i),Y_p^i) \]
其中,\(\bar V_p\) 是已经学好的某类物体的template mesh中属于部件p的那部分,\(Y_p^i\)是原始2D图像中属于部件p的那部分,\(N_p\) 是语义部件数量。
用Chamfer distance是因为投影后的顶点和原始的像素点并不是严格一对一对应的关系
用某类物体的template mesh,就可以让网络学相机pose;反之,假如用单个具体物体的mesh的话,网络就仅仅会对3D物体的形状进行扭曲,不会学到正确的相机pose了【我有点不理解为啥】
渐进的训练方法EM
之所以要用渐进式训练,是因为
- 需要3D重建模网络首先学会一个大体上可用的texture encoder \(I_{flow}\),然后才能生成标准语义UV map,
- 这样还能先生成对应具体类别的template mesh,一方面加速网络的收敛,一方面可以用在前面提到的基于顶点的约束中。
但是,如果直接把template mesh和重建模模型全都一起学习的话,效果不好;所以就提出了:EM训练步骤(expectation-maximization期望最大化?),就是先固定一部分学习另一部分。
E:固定标准语义UV map和template(初始是球体),训练重建模网络。200轮。
loss包括:
3D投影到2D的图像与gt剪影的 IoU ✖️ -1
3D投影到2D的图像与原始RGB图像的 perceptual distance(知觉距离?)
前面提到的基于概率的约束和基于顶点的约束
材质循环一致性 Texture cycle consistency:
image-20220124182432533 学习texture flow的时候最大的问题:颜色相似的3D mesh的面会被对应到错误的2D图像的像素点上
这是一个cycle:强制预测出来的texture flow(2D to 3D)和相机投影(3D to 2D)二者一致。
首先定义了\(\mathcal{C}_{in}^j\)、 \(\mathcal{C}_{out}^j\)分别是输入图像中被映射到三角形面\(j\)的一定数量像素点的几何中心,和从三角形面\(j\)渲染回2D图像时对应的一定数量像素点的几何中心。公式如下: \[ \mathcal{C}_{in}^j = \frac{1}{N_c}\sum^{N_c}_{m=1}\Phi(I_{flow}(\mathcal{G}^m))_j; \\ \mathcal{C}_{out}^j = \frac{\sum^{H\times W}_{m=1}\mathcal{W}_j^m\times \mathcal{G}^m}{\sum^{H\times W}_{m=1}\mathcal{W}_j^m} \] 其中,\(\mathcal{G}^m\)是投影图像的标准坐标网格(包含了像素的坐标\((u,v)\)值),\(\Phi\)是UV map,\(I_{flow}\)把像素映射到3D mesh的面\(j\)上;\(N_c\)是对应到面\(j\)的像素点的数量;\(\mathcal{W}\)是可微分渲染时生成的概率map,每个\(\mathcal{W}_j^m\)表示面 j 被投影到像素 m 上的概率。
- 把重建模mesh模型渲染成2D图像,用的是 Soft Rasterizer,而不是CMR中用的 Neural Mesh Renderer,因为前者可以提供概率map,供texture cycle consistency使用
那么,材质循环一致性就是让\(\mathcal{C}_{in}^j\)接近 \(\mathcal{C}_{out}^j\): \[ L_{tcyc} = \frac{1}{|F|}\sum^{|F|}_{j=1}||\mathcal{C}_{in}^j-\mathcal{C}_{out}^j||^2_F \]
还有写在附录里的两个loss:
- graph Laplacian constraint 来鼓励mesh表面平滑【从pixel-mesh中来的】
- edge regularization 来惩罚大小不规则的面 代码里似乎是flatten loss
还有写在附录里的对抗训练loss
M:利用训练好的重建模网络,更新template(从球体开始)和标准语义UV map。
template一开始是球体,然后每训练K轮,对它进行一次更新: \[ \bar V_t=\bar V_{t-1} + D_{shape}(\frac{1}{|\mathcal{Q}|}\sum_{i\in \mathcal{Q}}E(I^i)) \] \(V_{t}\)和 \(V_{t-1}\)是更新前后的template,I是输入的图片,经过E生成3D属性,D是形状 encoder。Q是经过某种方式选择出来的部分样本。
选择样本的方式:
- 首先选择最好的那一个样本,即与ground truth轮廓的IoU最小的
- 然后选择K个跟这个最好的样本最接近的样本,即这些样本的gt轮廓与最好的样本的gt轮廓的IoU越小则越接近
这样的话,template \(V_t\) 就是选出来的样本的平均形状
整个训练过程会包括两轮,每轮都包括一个E和一个M。(两轮分别就是代码中的
train_s1
train_s2
。)在E中,训练200 epoch 重建模网络,然后在M中用训练好的网络更新template和标准语义UV map。注意在第一轮中(一轮包括一个E和M),只训练重建模网络,而没有语义一致性约束。
实验
- 数据集:PASCAL3D+中的车和摩托车、CUB-200-2011中的鸟、ImageNet中的马 斑马 牛、OpenImages中的企鹅
- 局限性:
- 依赖于SCOPS提供语义分割,有时候语义分割不准确的话结果就不好
- 比较少见的相机pose很难
- 细节性的地方效果不好,比如正在飞的鸟的两个翅膀、斑马的腿等
Questions
为什么要stage2 ?
- 这两个 stage的主要区别就是:stage1的时候没有用语义一致性约束,在stage2才加上。因为一开始texture flow encoder效果并不好,avg_uv也不准确,所以干脆先不用。所以分成s1和s2,最主要的就是因为在s1训练完之后,重建模网络已经大体可以用了,这时候就可以调用
avg_uv.py
来生成标准语义UV map,供s2的时候语义一致性用。 - 附录里说,从效果上来看,2个stage比1个效果要好,且已经足够好了,有这张图对比了一下:
- 这两个 stage的主要区别就是:stage1的时候没有用语义一致性约束,在stage2才加上。因为一开始texture flow encoder效果并不好,avg_uv也不准确,所以干脆先不用。所以分成s1和s2,最主要的就是因为在s1训练完之后,重建模网络已经大体可以用了,这时候就可以调用
avg_uv 就是学 seg map -> uv map的么?
- seg map -> uv map这个过程是重建模网络中texture flow这个部分做的事情
- avg_uv就是论文里说的 标准语义 uv map(Canonical semantic uv map):
- 理论上,同一类物体的mesh模型,尽管各自都有不同的形状,但每个点的语义含义都是一致的
- 因此,对于某一类物体的大量图像数据集(比如鸟),可以生成一张对应这整个类别的avg_uv
- 利用这个avg_uv,相当于是给整个类别的template打上了语义标签,后续计算语义一致性约束的时候可以用。
- 这个avg_uv的计算过程:
- 首先用SCOPS(另一篇工作,无监督的)生成所有图像的语义分割结果seg map,然后用重建模网络学到的texture flow映射成uv map
- 选择效果最好的一部分instances,对它们的uv map取平均,得到avg_uv
paper 里面 有说固定camera 学shape? 那代码里有fix camera预测么?
我好像没有读到paper里有具体说到固定camera学shape耶……
论文里提到要解决camera-shape一起学时的ambiguity的问题,但不是固定一个学另一个,而是利用avg_uv来实现语义一致性:让 每个物体的2D seg uv map 与 avg_uv 保持一致性,从而让3D模型的每个语义部件跟2D图像里相应的位置有对应关系。
从这张图里可以看到,如果没有语义一致性,mesh模型中原本对应头的顶点被当作了翅膀尖,这样的camera就是错误的,错误的camera又造成了错误的shape。而有了语义一致性,就能利用语义让camera 更准确,这样就能跟着提升shape
按照他的说法, 先是feature avg 然后 decode 出 average shape。那么这个feature就要学好一点,否则平均容易成球形。那么这个feature 还有其他loss在上面么?比如我们smr 上还有 consistency loss 但是加在 delta_vertice上?他有加在feature上么?否则不能确保这个 feature avg 了以后 还有意义
我可能没有懂这个问题耶……学长说的是不是计算category level 的 template这个步骤呢?我觉得这个步骤里面保证效果好的方式有这几点比较关键:
- 更新category level 的 template是从M步骤才开始进行的;在此之前,E步骤中会在固定template的前提下,单独训练重建模网络200轮,这个过程中的loss还是挺多的,除了语义一致性没有用以外,其他的loss都用了,包括论文里提出的texture cycle consistency,还有附录里提到的graph Laplacian constraint、edge constraint等等
- 计算average template的时候,并不是用了所有数据,而是选择了最好的一部分instances:
- 首先选择最好的那一个instance,即与ground truth mask的IoU最小的
- 然后选择K个跟这个最好的样本最接近的样本,即这些样本的gt mask与最好的样本的gt mask的IoU越小则越接近
代码里面还放了一些 external的code,有用到么?
- 一个是SoftRas,用来把重建模mesh模型渲染成2D图像。论文里提到用它而不是CMR中用的 Neural Mesh Renderer,是因为它可以提供概率map,供texture cycle consistency使用
- 另一个是Neural Mesh Renderer,备选的renderer
- 再就是PerceptualSimilarity,用来计算了perceptual loss