2020和2021年,最火的计算机视觉技术非Transformer莫属。而除Transformer之外,最受欢迎也最有趣的技术我想应该是ECCV 2020的神经辐射场 (Neural Radiance Field, NERF) ,其核心点在于非显式地将一个复杂的静态场景用一个神经网络来建模。在网络训练完成后,可以从任意角度渲染出清晰的场景图片。
NeRF惊艳的效果吸引了大量研究者的关注,在20年3月挂上arXiv后,后续已经有大量的工作跟进,在速度、效果、动态场景等多个不同的角度对NeRF进行了改进。作为3D视觉里的一个新范式,学习后续的工作离不开对NeRF本身深入的理解。笔记中有不对之处欢迎指正。
Code: yenchenlin/nerf-pytorch
Awesome-Nerf: yenchenlin/awesome-NeRF
01算法概览
NeRF可以简要概括为用一个MLP神经网络去隐式地学习一个静态3D场景。为了训练网络,针对一个静态场景,需要提供大量相机参数已知的图片。基于这些图片训练好的神经网络,即可以从任意角度渲染出图片结果了。理解NeRF主要需要理解三个方面:
-
如何用NeRF来表示3D场景?
-
如何基于NeRF渲染出2D图像?
-
如何训练NeRF?
即我们要理解NeRF是如何从一系列2D图像中学习到3D场景,又是如何渲染出2D图像。
02用神经辐射场来表示场景
NeRF函数是将一个连续的场景表示为一个输入为5D向量的函数,包括一个空间点的3D坐标位置
,以及视角方向
。这个神经网络可以写作:
输出结果中,
是对应3D位置(或者说是体素)的密度,而
是视角相关的该3D点颜色。在具体的实现中,
首先输入到MLP网络中,并输出
和中间特征,中间特征和
再输入到额外的全连接层中并预测颜色。因此,体素密度只和空间位置有关,而颜色则与空间位置以及观察的视角都有关系。基于view dependent 的颜色预测,能够得到不同视角下不同的光照效果,非常惊艳。可以看出,NeRF函数的表示非常简单。
03如何从NeRF渲染出图片?基于辐射场的体素渲染算法
NeRF 函数得到的是一个3D空间点的颜色和密度信息,但当用一个相机去对这个场景成像时,所得到的2D 图像上的一个像素实际上对应了一条从相机出发的射线上的所有连续空间点。我们需要通过渲染算法从这条射线上的所有点得到这条射线的最终渲染颜色。同时,为了保证网络可以训练,NeRF中需要采用可微的渲染方法。
经典的volume rendering 方式
论文中首先介绍了经典的体素渲染volume rendering [2] 方法。体素密度 可以被理解为,一条射线 在经过 处的一个无穷小的粒子时被终止的概率,这个概率是可微的。换句话说,有点类似于这个点的不透明度。由于一条射线上的点是连续的,自然的想法是这条射线的颜色可以由积分的方式得到。将一个相机射线标记为 ,这里 是射线原点, 是前述的相机射线角度,t 的近段和远端边界分别为 以及 。那么这条射线的颜色,则可以用积分的方式表示为:
此处, 是射线从 到 这一段路径上的累积透明度,可以被理解为这条射线从 到 一路上没有击中任何粒子的概率。其具体的形式为:
但是,实际应用中,我们并不可能够用NeRF去估计连续的3D点的信息,因此就需要数值近似的方法。这里也是NeRF中非常核心的一个部分。
基于分段随机采样的离散近似volume rendering方式
一个直观且很常用的思路是,在需要求积的区域均匀地采样N个点进行近似计算。但作者提出,这样的方式会导致MLP只需要学习一系列离散点的信息,最终会限制NeRF的分辨率,使得最终生成的结果不够清晰。作为替代,作者提出了一种简单有效的方法,如上图所示,首先将射线需要积分的区域分为N份,然后在每一个小区域中进行均匀随机采样。这样的方式能够在只采样离散点的前提下,保证采样位置的连续性。第i个采样点可以表示为:
基于这些采样点,我们可以将上面的积分简化为求和的形式:
其中,
是邻近两个采样点之间的距离。此处
为:
同样,基于分段采样的渲染方式也是可微的。因此,基于这样的渲染方式,我们就可以用NeRF函数从任意角度中渲染出图片。
04NERF的训练过程
介绍完NeRF的基本原理,论文接下来介绍了NeRF中的两个重要Trick,以及训练方式。
训练高质量NeRF的重要技巧—— 位置信息编码
NeRF函数的输入为位置和角度信息,作者发现直接将位置和角度作为网络的输入得到的结果是相对模糊的(见实验部分)。而用positon encoding 的方式将位置信息映射到高频则能有效提升清晰度效果。具体而言,这里采用的是与Transformer 中类似的正余弦周期函数的形式。我的理解是,采用position encoding 能够使得网络更容易的理解并建模位置信息。
训练高质量NeRF的重要技巧—— 多层级体素采样
NeRF的渲染过程计算量很大,每条射线都要采样很多点。但实际上,一条射线上的大部分区域都是空区域,或者是被遮挡的区域,对最终的颜色没有啥贡献。因此,作者采用了一种“coarse to fine" 的形式,同时优化coarse 网络和fine 网络。这一部分也非常有趣。首先对于coarse 网络,我们可以采样较为稀疏的
个点,并将前述的离散求和函数重新表示为:
接下来,可以对
做归一化
此处的
可以看作是沿着射线的概率密度函数(PDF),如下图所示。通过这个概率密度函数,我们可以粗略地得到射线上物体的分布情况。
接下来,基于得到的概率密度函数来采样 个点,并用这 个点和前面的 个点一同计算fine 网络的渲染结果 。虽然coarse to fine 是计算机视觉领域中常见的一个思路,但这篇方法中用coarse 网络来生成概率密度函数,再基于概率密度函数采样更精细的点算的上是很有趣新颖的做法了。二阶段的采样示意图如下所示:
损失函数与一些训练细节
最后,训练损失的定义倒是非常简单,直接定义在渲染结果上的L2损失(同时优化coarse 和 fine):
训练时长方面,论文中提及的速度是一个场景要用单卡V100 训练1-2天左右。
05实验与讨论
view-dependence and positional encoding
这张图中的结果表明,加入位置编码能有效地提升结果的清晰度。而view-dependence 的颜色建模则使得建模的细节更好。
当然,view-dependence更重要的意义在于,它使得3D场景中的一个点在不同角度观察时呈现出不同的光照效果。非常酷炫。
Comparison with previous works
作者也对比了于此前一些方法的对比,不管是质量还是清晰度上都有非常大的提升。这里也不多描述了。
06小结
NeRF的效果非常酷炫,同时也提供了一种3D场景建模的新形式。NeRF本身当然存在很多的问题,最重要的是其渲染速度很慢,渲染一帧约要1分钟左右。但后续的新方法提出了很多优化的方式,大大优化了速度问题,也使得NeRF有了在实际场景应用的可能。除了速度,另外一个值得关注的点在于,NeRF本身就可以看作是对场景的一种conditional 的表示(NeRF中的视角就是一种condition),那么自然的想法就是拓展condition来建模动态场景。比如最近的AD-NeRF 就是将语音特征作为condition,使得NeRF可以实现Talking-head Animation 的效果。
总的来说,NeRF简洁的表示方式和优秀的效果带来了丰富的可玩性和拓展性,是非常棒的工作。此外,在论文附录中,还对论文中所使用的归一化设备坐标系(Normalized Device Coordinate, NDC)进行了详细的推导,感兴趣的话可以看看。
参考资料
[1] Mildenhall B, Srinivasan P P, Tancik M, et al. Nerf: Representing scenes as neural radiance fields for view synthesis[C]//European Conference on Computer Vision. Springer, Cham, 2020: 405-421.
[2] Kajiya J T, Von Herzen B P. Ray tracing volume densities[J]. ACM SIGGRAPH computer graphics, 1984, 18(3): 165-174.
作者:林天威
|关于深延科技|
深延科技成立于2018年,是深兰科技(DeepBlue)旗下的子公司,以“人工智能赋能企业与行业”为使命,助力合作伙伴降低成本、提升效率并挖掘更多商业机会,进一步开拓市场,服务民生。公司推出四款平台产品——深延智能数据标注平台、深延AI开发平台、深延自动化机器学习平台、深延AI开放平台,涵盖从数据标注及处理,到模型构建,再到行业应用和解决方案的全流程服务,一站式助力企业“AI”化。