基于深度学习的 3D 场景表示与三维重建。较早期而最知名的隐式 3D 表示。

2003.08934(2020 年 8 月)


这是啥?

NeRF 通过特殊的 3D 场景表示方式,实现:给定对同一场景的大量不同视角观测图片,神经网络经学习后可以(在某种意义下)理解这个场景的内容,并渲染出该场景在任意视角下的观测结果。

神经网络并不学到关于这个场景的 mesh 等信息;它学习的内容是观测结果。这也是为什么它被称为“隐式表示”。

为啥?

将一个 3D 场景视作一个 R5R4 的函数 f:((x,y,z),(θ,ϕ))((r,g,b),σ)。其中 p=(x,y,z) 表示场景中一个点;d=(θ,ϕ) 表示是从哪个方向观测它的;c=(r,g,b) 表示这时观测这个点看到的颜色;σ 表示体密度。

一般来说这个函数是连续的。

体密度 σ(p,d) 是一个体渲染中的概念。定义:一条光线从方向 d 射过来,在 p 被一个无穷小粒子挡住的概率。

理想不透明物体在任意点从任意方向观测的体密度为 1。体密度可以被理解为某种“不透明度”,不同浓度的雾是一种直观体现体密度差异带来视觉效果差异的例子。

如果我们得到了这个函数 f,那通过体渲染的方法,可以得到该场景任意视角的渲染结果。

啥是体渲染?

体渲染仅根据场景中每个点的颜色 c 和体密度 σ 渲染场景,而不借助任何 mesh 或光线信息。

相比于基于 Mesh 的渲染(面渲染?)中采用的光线追踪(Ray Tracing)方法,体渲染中的对应系列方法被称为光线行进(Ray Marching)。其特征是一条光线一直射到底,把沿路各种各样的东西积分起来。

考虑在摆放好相机位置后,从相机视角发射一条射线 r(t)=o+td,t[tn,tf],这条射线的颜色计算为

C(r)=tntrT(t)σ(r(t))c(r(t),d)dt

这个式子很好理解:射线第一次撞到粒子的颜色期望。T(t) 表示 [tn,t] 这一段一直没有被粒子挡住的概率,其计算式为

T(t)=exp(tntσ(r(s))ds)

头一次见到这么容易理解的式子,感动

当然为了精确地得到这个函数需要无穷次对场景的观测,这是不可实现的。我们用一个神经网络拟合它。神经网络的训练数据是一大批不同视角观测的结果。函数 f 大多数情况下是可微(?)的,这使得梯度下降等训练方法成为可能。

在 NeRF 的工作里,神经网络直接选用 MLP。

一些实现细节

首先是体渲染。计算这个积分时,将被积区间 [tn,tf] 均分为 N 份,每份均匀随机采样出一个点 ti,观察其颜色 ci 和不透明度 σi。然后估计的 Ti

Ti=exp(j=1i1σjδj)

其中 δj 为采样点 tjtj+1 的距离。然后

C^(r)=i=1NTici(1exp(σiδi))

为啥不直接乘 σi?因为这里的含义是在 [ti,ti+1] 内被至少一个粒子挡住的概率,而不能假设这个区间只有一个粒子。

换言之这其实不是暴力线性插值(把被积区间的体密度离散化),而是把被积区间的体密度视作分段函数。

可能会有很大差别,但没试过不知道

一个后续改进(多层级体素采样 Hierarchical volume sampling)通过将采样方式变得非均匀提高了计算效率。想法是同时训练两个网络(粗网络和细网络),粗网络采用较稀疏的 N,进行等分均匀采样;细网络基于粗网络得到的概率密度函数逆变换采样得到一堆密集点,它们在物体内部更密集而在空旷的地方更稀疏。

其次是网络输入。实验表明直接把五维信息输入效果不好,希望先把输入信息映射到高维,类似 Transformer encoder 的想法。

虽然看不太懂但映射函数是 γ:R[1,1]2L

γ(p)=(sin(20πp),cos(20πp),sin(2Lπp),cos(2Lπp))

然后对每个位置分量 L=10 每个方向分量 L=4 最后是一个 38 维的输入。

网络结构上,由于体密度与观测方向无关,所以输入的位置坐标先过一堆层得到一个 σ 和一组特征向量;特征向量连带着方向过另一堆层得到颜色。

训练细节好杂不想看,略。

其它

为啥叫“辐射场”(RF)?辐射场,即光场,是用于表达三维空间中光的分布和光强的一个模型。回顾 NeRF 对场景的描述(每个点在每个方向观测看到的颜色等信息),容易发现这其实是在描述整个空间所有点的光的信息。因此就叫光场了。感觉像随便起的名字

评论功能没修好,暂不开放