3D模型
3D三兄弟
在本篇日志中,我们尝试从多个角度审视世界模型。在此之前,我们需要介绍3D领域的三种模型
- 3D重建(3D Reconstruction):目标是从已有观测中恢复与真实场景相符的三维结构。输入可以是多张照片、视频或深度图;输出可以是相机位姿、深度图、点云、网格或其他三维表示。
- 3D生成(3D Generation):目标是根据文本、单张图像、多张图像或其他条件,合成一个合理的三维对象或场景。输出可能是三维网格、NeRF、3D Gaussian Splatting 表示,或可转换为三维资产的隐式表示。
- 3D世界模型(World Model):目标是学习环境状态及其变化规律,预测不同动作或条件下可能发生的未来。它可以使用三维重建结果作为输入或监督,也可以直接在潜在空间中预测未来,不一定需要显式重建完整的三维网格。
上述三者的区别可以用下面这个例子解释:从一段行车视频恢复道路、车辆和相机轨迹,属于 3D 重建;根据一张汽车照片生成可从任意视角观察的三维汽车,属于 3D 生成;根据当前场景和自车动作预测下一时刻车辆及行人的空间状态,则属于世界模型的任务。
多视角几何基础
在之前的日志中,我们介绍了单目相机学的基础知识,其核心原理在于使用单个相机的观察结果获取物体在3D世界系下的位置。对于世界系坐标 Xw,我们通过相机内外参数得到其像素系坐标 x。
在齐次坐标下,可以得到
λx~=K[R∣t]X~w
在真实的 3D 重建中,我们往往只知道二维图像,不知道三维点的位置,也不知道相机之间的相对位姿。多视角几何(Multi-View Geometry)研究的正是如何利用不同视角的图像,恢复这些未知量之间的关系。
对于我们人的双目系统来说,人的左眼和右眼分别可以看见两幅有视差的图像。进而在大脑中可以形成有景深的立体图像。用数学表达:设某个三维点 Pw 在两个相机的像素系坐标为 x1,x2,现在来看这个双目几何下的系统具有怎样的性质。
以第一台相机 X1=(xc1,yc1,zc1)T 为世界参考系原点,其相机系等于世界系,即有 R1=I,t1=0。三维点 Pw 在该相机坐标系(世界坐标系)下的坐标为 Xw,而第二台相机相对于第一台相机的变换可以记作
X2=R21X1+t21=(xc2,yc2,zc2)T
根据单目几何知识,有
X1=zc1K1−1x~1,X2=zc2K2−1x~2,
代入相机之间的变换式有
zc2K2−1x~2−zc1R21K1−1x~1−t21=0
此时的式子中有未知量 zc1,zc2,R21=R,t21=t。考虑一个极平面(Epipolar Plane),其由两相机的光心点 C1,C2 和三维点 Pw 确定。下图展示了一个双目几何系,其中的极平面是该系的核心。
[{"url":"https://images.openai.com/static-rsc-4/tkVoggHAD5bsHfahPB70bNIFZPwh62PnYFfq5iB62bobsXTF571N2SnrV_EbJb0blsH9rWBunZBPd-oAXvGp0C1DPaxvxWC00ZNzICbFEXaIbmRnIHu5sh02v0B82cIsTIPTogkJonH5BYtWKWgtCei5Pwe91KOOKaFrATW3p8XTC5-356lj0RLK6NqAJX4I?purpose=fullsize","alt":"三角定位","title":""}]
考虑表示简便,有成像面坐标 q~1=K1−1x~1,q~2=K2−1x~2。上式表明向量 q~2,Rq~1,t 共面,因此它们的混合积为0。现在考虑一种更简便的表示,先把混合积形式写出来
q~2T(t×Rq~1)=0
定义 t 的反对称矩阵 [t]× 满足 t×a=[t]×a,因此改写上式为
q~2T[t]×Rq~1=0
此时的 [t]×R 被称为本质矩阵(Essential Matrix)约束,记作 E。本质矩阵不描述三维点的具体位置,而是描述两个视角之间的几何约束,即有下式始终成立
q~2TEq~1=0
现在把上式改写成关于像素系坐标的约束式,根据记号规定有
x~2T(K2−1)TEK1−1q~1=0
再定义基础矩阵(Fundamental Matrix) F=(K2−1)TEK1−1,其描述了原始像素坐标之间的约束关系,即有 x~2TFx~1=0
双目几何系通过上述约束关系,主要想解决下述三个问题
- 位姿恢复:从本质矩阵分解出相机之间的相对旋转和平移方向。
- 三角化:已知相机位姿和对应像素,通过两条观测射线恢复三维点。
- 多视角扩展: 将两张图像推广到 N 张图像,让更多观测共同约束同一个三维点和多台相机的位姿。
为此可以引入深度的概念,对于一个双目几何系,同一世界系的点 Pw 在像素系中的水平坐标差为 d,基线为两相机的光心连线长度 B=C1C2,此时就可以估计点 Pw 的深度坐标 Zw(也就是相对于第一台相机系/世界系的 Zc 轴坐标)为
Zw=dBfx
对于多相机系的引入,可以基于双目几何系构造多组约束并最小化误差,得到更精确的估计。
传统3D重建
3D表示与渲染
一个三维物体通常拥有多种3D表示方法,本节分别做介绍。最基础的方法是使用网格近似表示一个物体表面,而三角网格(Triangular Mesh)是计算机图形学中最基本的3D表示形式。一个三角网格 M 可以定义为一个二元组
M=(V,F)
其中的 V 是顶点集合,F 是顶点集合。若使用多边形网格,还需要存储边集合信息 E。
点云表示是另一种常用方法,是最原始的3D数据表示方法之一。每个点 pi=(xi,yi,zi) 表示三维空间中的一个点,而众多的点组合在一起便得到了一片点云 P。此时可以为点附加额外信息,以增加携带信息。
体素(Voxel)将3D空间离散化为规则网格,每个体素存储占据信息或属性值,这可以看做点云的离散化表示。此时的每个体素可以被视作一个有体积的微小实体。
最后,我们还可以使用隐式场表示法,通过连续函数 f:R3→R3 定义物体表面
S={x∈R3∣f(x)=0}
[{"url":"https://pica.zhimg.com/v2-be3cfee6038f39557dc2903f8512c0b6_1440w.jpg","alt":"3D表示","title":""}]
一般流程
传统 3D 重建通常以多张具有重叠视野的 RGB 图像或视频帧为输入,通过相机位姿估计、三维几何恢复和表面重建,最终生成三维点云、网格模型或带纹理的 3D 场景。经典的照片级重建流程可以概括为图像采集 → SfM → MVS → 点云融合 → 表面重建与纹理映射。
具体流程叙述如下:
- 图像采集与相机标定:首先从不同视角拍摄同一个静态场景,保证相邻图像具有足够的重叠区域。如果相机内参未知,可以通过棋盘格标定或自标定估计焦距、主点和镜头畸变参数。
- 运动恢复结构(Structure from Motion, SfM):SfM 首先提取并匹配不同图像中的特征点,通过基础矩阵或本质矩阵进行几何验证,再估计相机之间的相对位姿 Rij,tij。随后利用三角化恢复稀疏三维点云,并逐步估计其他图像的相机位姿。最后,通过光束法平差(Bundle Adjustment, BA)联合优化相机参数和三维点,降低整体重投影误差。SfM 的主要输出是相机位姿和稀疏三维结构。
- 多视角立体重建(Multi-View Stereo, MVS):在相机位姿已知或经过优化后,MVS 利用多个视角之间的图像对应关系,估计每个视角的稠密深度图。与 SfM 主要恢复少量可靠的特征点不同,MVS 会尽可能为更多像素恢复深度,从而补全物体表面和场景细节。
- 点云融合与过滤:将不同视角的深度图结合相机内外参反投影到三维空间,再转换到统一坐标系中进行融合,形成稠密点云。
- 表面重建与纹理映射:稠密点云仍然只是离散的三维采样点,并不是完整的连续表面。表面重建算法会进一步生成三角网格等几何表示,之后将原始图像的颜色信息映射到网格表面,生成带纹理的三维模型。
NeRF
基本思想
NeRF全称为神经辐射场(Neural Radiance Fields),其旨在解决一个3D重建中更本质的问题:给定若干张不同视角的照片,如何构建一个三维场景表示,使我们能够从任意一个新视角重新渲染出合理的图像?
由于真实的几何表示对于传统3D重建模型具有很大的挑战,NeRF 不再把重点放在直接恢复一张显式的三维网格上,而是学习一个能够解释所有训练图像的连续场景函数。
NeRF 不是把多张图片简单拼接起来,也不是直接预测一张完整的三维网格。它学习的是一个可以在三维空间中被反复查询、并通过渲染解释观测图像的函数。
隐式3D表示
隐式3D表示,就是不直接存储空间中每个位置的属性,而是用一个函数,根据输入的空间坐标计算相应属性。考虑一个参数为 θ 的神经网络,其对应一个连续函数
Fθ:(x,d)→(c,σ)
其中的 x∈R3 为空间查询位置,d∈R3 表示单位观察方向,c∈R3 表示三通道 RGB 值,σ⩾0 表示对应位置的体密度。由于单位观察方向只具有两个自由度,因此上式对应的神经网络称为5D辐射场。
上式将观察结果总结为当前视角的颜色观测和对应位置体素的透光倾向,这是对真实观察的一种近似。NeRF 因此被总结为一个输入三维位置与观察方向,输出颜色与密度的神经网络。
[{"url":"https://pic3.zhimg.com/v2-5b9e036c9935483d081f0c4b3e07b0ce_1440w.jpg","alt":"NeRF","title":""}]
神经辐射场
根据 NeRF 的构造函数,这个网络还不能直接生成一张图像,因为其输出的是一个高维表示 (c,σ),我们还需要把三维空间中的颜色与密度转换成二维像素,以图像的形式给出结果。这一步可以由相机模型简单的给出,不在此赘述。
设某像素的齐次坐标为 x~,其在相机系的归一化坐标为 q~=K−1x~,因此其对应的单位射线向量为
dc=∥q~∥q
由于相机系和世界系的关系满足 Xc=RXw+t,因此相机光心在世界系的位置为
o=−RTt
此时的射线向量和射线表示就记为
dw=RTdc,r(t)=o+tdw
因此,沿该射线采样若干点 ti 就得到了若干组对应关系 (xi,dw)→(ci,σi)。现在的问题在于如何通过若干个采样点的颜色输出一个最终结果。显然,我们不能简单取最近点的颜色,也不能把所有采样点的颜色直接平均,因为前面的物体可能遮挡后面的物体。因此,最终像素颜色需要同时考虑三个因素:
- 光线能否到达当前位置。
- 光线在当前位置被终止的概率。
- 当前位置的颜色。
考虑辐射的定义,在该射线上定义透射率
T(t)=P(光线从近端到达 t)
如果局部密度为 σ,那么光线穿过长度为 Δt 的小区间时,可以近似认为其存活概率为
P(光线穿过 Δt)=e−σΔt
利用微积分的思想,可以得到一个积分
T(t)≈exp(∫tntσ(r(τ))dτ)
其中的 tn 为人为设定的 ti 取值下界,按照原文有 ti∈[tn,tf]。上式直观解释为:当前位置之前的所有密度都会影响光线的可见性。如果前方密度很低,透射率就接近 1;如果前方已经经过一个高密度区域,透射率就会下降。
颜色渲染
考虑射线上的一个极短区间 [t,t+dt],要让这个位置对最终像素产生贡献,光线必须先到达这里,再在这个小区间内被终止。光线在该小区间内被终止的概率近似为
σ(r(t))dt≈1−e−σΔt
光线需要先到达 t,由乘法公式得到光线该区间内终止的概率近似为
T(t)σ(r(t))dt
如果该位置沿观察方向 d 的颜色为 c(r(t),d),那么它对像素颜色的贡献就是:
dC=T(t)σ(r(t))c(r(t),d)dt
将射线上的所有贡献累加,就得到 NeRF 的连续体渲染公式
C(r)=∫tntfT(t)σ(r(t))c(r(t),d)dt
细节处理
神经网络无法直接对无限多个连续位置逐点计算,因此在实际实现中,我们必须对射线采样,再用有限个样本近似积分。考虑射线上的若干个采样点
t1,t2,⋯,tN
定义相邻采样位置之间的距离 δi=ti+1−ti,在该区间内近似密度为常数 σi。通过和连续情况类似的推导,可以得到 NeRF 中的离散体渲染公式
C^(r)=i=1∑NTi(1−e−σiδi)ci
此外,论文作者通过实验发现:对于位置输入 x 执行类似于 Transformer 的正余弦位置编码后,将大大提升神经网络的训练和表现效果。另外的一个细节是采样方法,原论文使用了分层采样的方法,构造了粗、细网络以进行不同细粒度的采样。
训练与使用
对于经典 NeRF,训练一个具体场景通常需要以下内容
- 多张该场景的 RGB 图像
- 每张图像对应的相机内参与位姿
- 场景的近端与远端采样范围
对某一批训练射线上计算基于 RGB 值的损失函数
L=r∈R∑∥Cθ^(r)−C(r)∥2
然后通过梯度方法优化参数。最终,网络学到的并不是一张二维纹理图,而是一个能够在不同三维位置和观察方向上返回颜色与密度的连续函数。只要给定新的相机位姿,就可以重新生成射线、查询场景函数并进行渲染,从而合成训练时未直接观测过的视角。
通常,经典 NeRF 通常需要针对每个场景单独优化。下一篇(预告)所介绍的前馈式重建模型则利用大量训练场景预先学习参数,在使用时直接输入新场景并一步前馈输出。
Gaussian Splatting
简述
前文介绍的 NeRF 使用辐射场的概念实现了 3D 隐式重建,而后期工作3D高斯泼溅(3D Gaussian Splatting)提出了一种新方法,实现了辐射场的实时渲染,能够在较少的训练时间中,实现SOTA级别的视觉效果。3D 高斯泼溅的核心可以概括为:使用 3D Gaussian 球表示三维模型,并通过 Splatting 技术渲染出来。
[{"url":"https://picx.zhimg.com/v2-07eae83c38038dc88442f60db166fce9_1440w.jpg","alt":"GS","title":""}]
高斯分布
高斯分布是一种常见的概率分布,以一维形式有
f(x)=2πσ1e−2σ2(x−μ)2
一维形式的高斯分布又被描述为钟形曲线,现在考虑三维高斯分布形式
f(x)=2π3∣Σ∣1exp[−21(x−μ)TΣ−1(x−μ)],x∼N(μ,Σ)
其中的符号解释为
- x=(x,y,z)T:三维点坐标
- μ=(μx,μy,μz)T:均值向量
- Σ:协方差矩阵,其满足如下分解形式
Σ=RSSTRT,S=diag(sx,sy,sz),R∈SO(3)
对于一个三维函数 f(x)=a,其解构成一个椭球面。在协方差矩阵的分解式子中,对角矩阵 S 的元素反应了这个椭圆在三维正交方向的伸缩系数,旋转矩阵 R 表示其旋转朝向。
仿射变换与透视投影近似
现在考虑一个仿射变换 y=Ax+b,根据高斯分布的均值和协方差定义,这等价于把一个高斯分布 N(μ,Σ) 变为新的高斯分布 N(Aμ+b,AΣAT)。这个结论非常有用,因为我们需要对不同坐标系下的高斯分布进行转换。
现在考虑三维高斯转化为二维,这个过程称为泼溅(Splatting)。相机系坐标到像素系坐标有
u=fxzcxc+cx,v=fyzcxc+cy
注意到其中包含非线性项 zcxc,zcyc,因此三维高斯分布投影到二维平面上不再是高斯分布。然而,我们仍然希望投影结果具有高斯分布的良好性质,因此可以做投影近似,设投影矩阵为
(u,v)=π(x)=fxzcxc+cxfyzcxc+cy
其雅可比矩阵为
J=zcfx00zcfy−zc2xfx−zc2yfy
根据一阶泰勒展开,在高斯分布中心 μ 附近有
π(x)≈π(μ)+J⋅(x−μ)
现在起,假定高斯分布 N(μ,Σ) 为世界系表示。若世界系到相机系的旋转矩阵为 W,那么相机系表示的协方差矩阵为 WΣWT,像素系表示的近似高斯分布协方差矩阵为 JWΣWTJT。
球谐函数
现在几何已经可以投影到图像上了,但还有一个问题:高斯的颜色应该如何确定?如果每个高斯只存储一个固定 RGB 颜色,就很难表示某些随观察方向变化的外观,因此需要考虑类似于 NeRF 的颜色观察机制。即考虑颜色关于观察方向的函数
c=f(θ,ϕ)
其中的 (θ,ϕ)=d 表示一个三维单位方向向量,其所有取值位于一个单位球面上,因此需要考虑一个函数映射 f:S2→R3。为了表示这个函数,可以使用一组固定基函数的线性组合,3DGS 使用球谐函数(Spherical Harmonics)来近似,一般形式为
c(θ,ϕ)=l=0∑Lm=−l∑lhlm(i)Ylm(θ,ϕ)
其中,Ylm 是下述形式的球谐基函数(了解即可,长得的确可怕),l 表示球谐阶数,L 表示使用的最高阶数,m=0,±1,⋯,±L 表示同一阶基函数的索引,而 hlm(i) 是可学习的系数。
Ylm(θ,ϕ)=4π2l+1(l+m)!(l−m)!Plm(cosθ)eimϕ
可以证明,最高阶数为 L 时,基函数的总数为
NSH=(L+1)2
原始 3DGS 通常使用最高 3 阶球谐函数,因此每个颜色通道有 16 个系数,总计 16×3=48 个颜色系数。
光栅合成
对于一个相机系的三维高斯分布 N(μc,Σc),我们将其投影为一个近似二维高斯分布,即有
μp≈π(μc),Σp≈JΣcJT
对于像素坐标 p=(u,v)T,其对应的高斯权重定义为
gi(p)=exp[−21(p−μp)TΣp−1(p−μp)]
为了学习单个像素的不透明度,先定义该高斯分布的全局可学习参数 oi,其不随像素位置变化。现在把这个参数和对应的高斯权重相乘,得到单个像素的有效不透明度
αi(p)=oigi(p)
类比 NeRF,可以得到第 i 个高斯分布前方的透射率为
Ti=j=1∏i−1(1−αj)
因此可以得到颜色表达式
C=i=1∑TTiαici+TN+1Cbg
其中的 Cbg 为背景颜色,上式就是前向透明度合成形式。
训练
3DGS 中,一个高斯包含以下可学习参数 (μi,Σi,oi,h(i))。给定一组训练照片,3DGS 用这些参数渲染预测图像 I^,再与真实图像 I 比较。原论文使用的损失函数为
L=(1−λ)L1+λLD−SSIM
其中的 L1 反应了 RGB 像素的 L1 误差,LD−SSIM 衡量图像结构差异。原始 3DGS 使用 SfM 重建得到的稀疏点云初始化高斯中心,这是因为稀疏点云已经提供了场景的大致几何结构。
3DGS的可讲内容很多,此篇博客仅做基本原理讲解。