目录
体积渲染的数值估计(Numerical estimation of volume rendering)
分层体积块采样(Hierarchical volume sampling)
NeRf论文精炼:https://www.cnblogs.com/noluye/p/14547115.html
NeRF-pytorch源码GitHub:https://github.com/yenchenlin/nerf-pytorch.git
为什么需要Nerf
Nerf(Neural Radiance Fields)是一种用于实现高质量、高效的光线追踪的方法。传统的光线追踪方法需要对每个像素进行单独的采样和渲染,计算量非常大,尤其是在处理复杂的场景时,计算时间会变得非常长。相比之下,Nerf 可以在单次前向传播中直接计算整个图像,从而避免了单独的采样和渲染过程,大大减少了计算量和时间。
另外,Nerf 还可以处理非常复杂的场景,包括光线穿过透明物体、光线反射和折射等复杂的光线行为。这些场景对于传统的光线追踪方法来说非常具有挑战性,但是对于 Nerf 来说却相对容易处理。
除此之外,Nerf 还可以实现全景图像合成,可以在单个场景中捕捉多个视角的信息,并将它们融合成一个连续的全景图像。这种技术可以应用于虚拟现实、增强现实等领域,可以提供更加逼真的虚拟场景体验。
Nerf的过程
Nerf(Neural Radiance Fields)的过程可以分为两个主要步骤:场景重建和渲染。
场景重建
场景重建是指从输入的图像和相机参数中,通过训练神经网络来重建场景的 3D 几何结构和光照信息。具体来说,Nerf 使用了一种基于神经网络的函数拟合方法,将每个像素的颜色和不透明度表示为场景中的位置和方向的函数。这些函数被称为神经辐射场(Neural Radiance Fields,NRF),可以通过神经网络训练得到。
场景重建的过程可以分为以下几个步骤:
输入图像和相机参数,生成光线:对于图像中的每个像素,根据相机参数生成一条从相机位置出发的光线。
采样光线路径:对于每个光线,从相机位置到场景中的某一点沿着光线进行采样,得到一组采样点。
计算神经辐射场:对于每个采样点,通过神经网络计算其颜色和不透明度。
重建场景:通过插值和积分等方法,将神经辐射场转换为场景的 3D 几何结构和光照信息。
渲染
渲染是指将重建的场景图像转换为最终的渲染图像。具体来说,对于给定的相机参数,可以通过场景重建得到场景中的 3D 几何结构和光照信息,然后使用类似传统光线追踪的方法,计算每个像素的颜色。
渲染的过程可以分为以下几个步骤:
输入相机参数,生成光线:对于图像中的每个像素,根据相机参数生成一条从相机位置出发的光线。
采样光线路径:对于每个光线,从相机位置到场景中的某一点沿着光线进行采样,得到一组采样点。
计算颜色和不透明度:对于每个采样点,通过神经网络计算其颜色和不透明度。
计算最终颜色:通过插值和积分等方法,将采样点的颜色和不透明度转换为像素的颜色。
Nerf 的过程通过神经辐射场将场景的 3D 几何结构和光照信息进行了紧密的耦合,使得模型可以同时重建和渲染场景。这种方法可以高效地处理复杂场景,并且可以实现全景图像合成等应用。
Nerf的输入输出分别是什么
给定一组连续拍摄的图像+姿态,Nerf尝试使用光线位置、光照方向、对应三维坐标(x,y,z)为输入,输出目标的密度(形体)+颜色。输入共计五变量,也因此被称为“5D辐射场”。具体来说,给定空间点坐标(x,y,z)与观测方向(d_x,d_y,d_z中任意两个,第三个通过叉乘求出,俗称“知二得三”)可求解得该点的密度值(其实是光线在该点终止的概率)与对应的颜色(RGB值)。预测了颜色值,和当前姿态下对应的输入图片求损失,则可进行优化使模型逐步收敛。
Nerf模型如何渲染
相关知识
体渲染
“体渲染”一词通常用于形容在3D计算机图形学中的一种技术,即将数字模型转换为真实感的图像。这种技术通常使用光线追踪、阴影、反射、折射、纹理映射等方法来模拟光线在现实世界中的行为,从而让数字模型在图像中呈现出真实感、立体感。
在计算机动画、电影特效、游戏开发等领域,体渲染技术被广泛应用。通过这种技术,可以创建出逼真的虚拟世界,让观众感受到身临其境的视觉效果。
体密度和颜色
体密度和颜色是在体渲染中非常重要的概念。
在3D计算机图形学中,数字模型通常是由许多小的立方体单元(称为体素)组成的。每个体素都有一个密度值和颜色值,用于描述该体素在物理上代表的物质的密度和颜色。密度值通常用于模拟物体内部的光线传播,决定了光线在经过该体素时的衰减程度。颜色值则决定了体素在图像中的颜色,它通常是由物体表面的材质、光照等因素决定的。
在进行体渲染时,计算机会根据每个体素的密度值和颜色值,计算出光线在该体素内部的传播情况,并将结果合成为最终的图像。这个过程可以通过光线追踪等算法来实现,其目的是让数字模型在图像中表现出真实的外观和材质。
渲染具体
Nerf引入了经典的体渲染理论来进行色彩与密度(也就是Nerf输出值)的建模。
相关物理公式如下(实际使用该公式的离散化形式):
体渲染方程
这个公式看上去极度复杂;里面涉及三组物理量:光线累积量T(x) 、体素密度 (x) 与颜色 C(x)
体素密度 (x) 反映了该模型在该光线的某处的粒子的密度,也就是一个具体的三维坐标上粒子的密度
颜色 C(x) 反应了该具体的三维坐标上,从光线的方向看去,粒子反射的颜色
光线累积量 T(x) 是一个随着光线的路径长度增加,而不断对体素密度积分的量,它的大小是随着光线达到的地方深度的增加而逐渐减小的,也就是说透明度在不断的下降,光线没有碰撞到任何粒子的概率在减小
据此可以设想体渲染方程的物理意义:解决了遮挡问题与无界问题。
举个例子:在追踪某一条光线并在积分的过程中,假设环境是真空的,如果实际的场景中第一个物体遮挡住了第二个物体,那么光线在经过第一个物体的时候,粒子碰撞到物体表面的概率是非常大的。因为对于一个具体的物体而言,它所在的位置的粒子密度肯定是在一定量级上且比较大的。所以当光线通过第一个物体之后,到达第二个物体的时候,T因为穿透前一物体而释放能量,剩余累积量已经很小了,因此按照比例,第一个物体对于颜色的贡献,会大于第二个物体。换句话说,在追踪这根光线上,主要(应该说是几乎全部)呈现的是第一个物体粒子所反射的颜色,而第二个物体粒子的颜色的影响微乎其微。这和实际物理建模的结果是相互呼应的。
了解了如何进行渲染后,我们进一步介绍nerf进行体渲染的方法:分层体素渲染(Hierarchical volume sampling)。
这里还是要先解释一下背景:直接使用上面公式中的体渲染积分,需要控制采样起始点。如果直接对全局采样,所需要的计算消耗过大,且采样区间的点较为稀疏。假设使用均匀分布采样,则直接采样效率低。选择恰当的起始、终止点在这里是非常重要的。选择起始点区间长度太小,则采样点不足,影响训练结果。基于体渲染方程分析,一个合理的采样选择是,最好尽可能的避免在空缺部分以及被遮挡了的部分进行过多的采样,因为这些部分对最好的颜色贡献是很少的。
那么如何采样效率最高呢?Nerf使用两个网络同时进行训练 (后称 coarse 和 fine 网络), coarse 网络输入的点是通过对光线均匀采样得到的,根据 coarse 网络预测的体密度值,对光线的分布进行估计,然后根据估计出的分布进行第二次重要性采样,然后再把所有的采样点一起输入到 fine 网络进行预测。具体过程请见下图。
左图:粗采样 右图:细采样
分层体素渲染的具体流程如下:
先使用粗采样(在起点、终点之间均匀采样)得到 个点,采样通过 coarse 的渲染方程的计算。
离散化采样方程
之后需要对 进行归一化,得到分段常数概率密度函数,然后通过逆变换采样(inverse transform sampling)获得N_f个点,添加至已有点中,用于fine网络采样。
简单说一下这里为什么用逆变换采样。逆变换采样的作用是,在分布 p 的 CDF 值域上均匀采样,其采样结果与原分布 p 中的采样同分布。因此如果获取当前分布困难,可以通过逆变换采样,简化问题难度。
体积渲染的数值估计(Numerical estimation of volume rendering)
解释:在体积渲染中,需要对场景中的体积进行采样,并将采样结果插值为图像或视频。这个过程通常涉及到对采样值的数值估计,以生成最终的渲染结果。
数值估计在体积渲染中非常重要,因为它直接影响着最终渲染结果的质量和准确性。常见的数值估计方法包括线性插值、三次样条插值、立方体插值等。
线性插值是一种基本的数值估计方法,它通过对相邻采样点之间的线性插值来计算任意位置的采样值。三次样条插值则是一种更高级的插值方法,它通过拟合曲线来计算采样点之间的任意位置的值。立方体插值则是一种基于立方体的插值方法,它通过对相邻采样点之间的立方体进行插值来计算任意位置的采样值。这些方法都在体积渲染中得到了广泛的应用,并且在不同的场景和应用中都具有一定的优劣势。
除了插值方法之外,还有一些其他的数值估计方法可供选择。例如,有些方法将采样点周围的体积块视为一个局部区域,并对该区域进行拟合或计算。这些方法可以提高数值估计的准确性和鲁棒性,但通常需要更多的计算和内存资源。
总的来说,数值估计是体积渲染中一个非常重要的环节,对最终的渲染结果具有直接的影响。在选择数值估计方法时,需要根据具体的应用场景和需求进行选择,并综合考虑估计的准确性、计算效率和内存占用等因素。
注意到体素渲染方程是连续形式,而在实际神经网络训练过程中无法完成的。因此需要将其改为离散形式进行近似计算(Quadrature积分法)
通过将视线路径均分成 N 段,然后在每一段均匀地随机采样体素用于渲染计算。
分层体积块采样(Hierarchical volume sampling)
解释:分层体积块采样(Hierarchical Voxel Sampling)是一种用于加速神经渲染算法的采样技术。在渲染过程中,需要对场景进行采样以生成图像或视频。由于现实场景通常非常庞大,因此采样操作可能需要大量的计算时间和空间。分层体积块采样可以将采样操作分解为多个层次,从而实现更高效的采样。
具体来说,分层体积块采样将场景划分为多个较小的体积块。在开始渲染时,首先对最大的体积块进行采样。然后,对于每个采样点,可以进一步对其所在的子体积块进行采样。这个过程可以继续迭代下去,直到达到所需的采样精度为止。
通过这种分层的采样方式,可以大大降低采样操作的计算时间和空间占用。这是因为对于大多数采样点,只需要在最高层级的体积块中进行采样,而不需要对更深层次的体积块进行采样。只有在需要更高精度的情况下,才需要进一步迭代下去并对更深层次的体积块进行采样。
分层体积块采样在神经渲染算法中得到了广泛应用,特别是在处理大规模场景时。通过这种技术,可以实现更高效的采样操作,并且可以在一定程度上减少计算时间和内存占用。
在场景中难免会存在 free space 和 occluded regions 这种应该对渲染结果无贡献的区间,或者说没有意义的。为了更有效地采样,本文采用分级表征渲染的思想提高渲染效率,即通过同时优化两个神经网络:"coarse"和"fine"。
位置编码(Positional encoding)
为什么要引入位置编码:传统的MLP网络不善于学习高频数据信息,但是基于颜色的纹理信息都是高频的,如果直接使用MLP学习,会导致学得纹理的表面相当模糊。因此引入了位置编码,让MLP同时学习高低频信息,提升清晰度。
MLP 通常由多层的参数矩阵组成,在计算即前传的过程中,还存在着大量的非线性激活,这使得 MLP 具有非常良好的插值性质,能够输出足够平滑的结果(我们老师将之称为 Deep Prior,我个人理解是属于 MLP 的 inductive bias),但这也意味着 MLP 难以捕获到变化剧烈的区域的特征(即高频特征)。 对于 Positional Encoding,从一方面来讲,它将欧式空间的样本点投影到频率空间,也就是将点打散了,在欧式空间相近的点在频率空间就会很远。原本 MLP 很难拟合出“狭小”的欧式空间中的剧烈变化。但在 Positional Encoding 将样本点投影到频率空间后,这些“剧烈变化”在频率空间就显得平滑得多, MLP 就能够很轻易地在频率空间拟合出这些变化,但频率空间相较于欧式空间得求解空间大得多,所以 MLP 依旧需要花费大量的时间去拟合。 从另一个角度来说,NeRF 想做的事情是表征欧式空间中的一个场,而 Positional Encoding 则是对欧式空间的三个轴分别引入了一组正交基函数,此时 MLP 的任务就可以看作是学习得到这三组正交基函数的系数表示,这个任务相比于让 MLP 去拟合高频特征显然要简单得多
虽然前文描述的“隐式表示+体素渲染”十分美好,但是我们通过下图(No Position Encoding)可知它的生成图片十分模糊(可以理解为一种高频信息丢失)。前人工作指出神经网络倾向于学习低频信息,而NeRF需要重建高清的场景(对场景overfitting),所以我们需要让模型关注场景的高频细节。于是将位置向量 x 和方向向量 d 转化为高频变量:
训练自己的数据集
参考:
NeRf论文精炼:https://www.cnblogs.com/noluye/p/14547115.html
NeRF-pytorch源码GitHub:https://github.com/yenchenlin/nerf-pytorch.git
数据下载
bash download_example_data.sh
安装好后的数据集文件夹:
输入指令训练数据
python run_nerf.py --config configs/lego.txt