NERF基本原理

1、NERF的目的

输入一系列的已知视角,优化NeRF来表示连续场景,最后渲染出该场景的新视角。
请添加图片描述图1

2、NERF细节

2.1、隐式表达

假设我们用NeRF学习了一个确定场景,那么这个场景被隐式地保存在NeRF神经网络的参数中,假如我们需要得到一个新视角的画面,我们需要用神经网络计算出这个画面各个位置的光线和颜色值。与之相对的就是显式表达。
为了更方便理解,我用2D图像表示来举例:
我们有一张2D图像,像素点的坐标是 (x,y),像素点的颜色是 (r,g,b)。既然坐标和颜色是一一对应的,可以构建一种映射关系:
f(x,y)=(r,g,b)
这种映射关系可以被神经网络来表达:
(x,y)->NN->(r,g,b)
我们可以对图像采样一些随机点当作神经网络的训练数据,然后可以用训练好的神经网络来推理这张图像其他位置像素值。这里很好理解,我们直接将这种情况推广到3D,就可以得到NeRF的基本结构。NeRF的公式表达:
FΘ:(X,d)→(c,σ)
X=(x,y,z)表示3D点的坐标,d=(θ,ϕ)表示观测方向,c=(r,g,b)表示3D点预测出来的颜色值,σ表示体密度。由2D平面推广到3D空间要考虑很多东西,首先一点就是观测角度会影响3D点的颜色表现。所以,整个NeRF的设计就是一套view-dependent的思路,所以NeRF的输入除了3D位置以外,还需要观测角度,一共需要5D向量作为输入,即 (x,y,z,θ,ϕ)。输出结果为该3D点的像素值c和体密度σ,这两个输出可以用来进行体渲染(volume rendering)。

2.2、nerf的输入与输出

camera ray:相机射线
请添加图片描述图2
图c中的函数就是概率密度函数,ray1视角下,光线经过铲车得铲子后被阻挡,所以只有一个波峰。ray2因为是侧视角,所以光线没有一次被完全遮挡,所以有两个波峰。波峰在此处就说明在这个点密度σ很大,

上图中可以看到,nerf的输入是5维(x,y,z,θ,ϕ),输出是4维(r,g,b,σ)。
表示观测方向的两个输入参数(θ,ϕ)的示意图如下:
请添加图片描述图3
粗略可以理解为ϕ代表俯仰(点头),θ代表偏航(摇头)。
对于某已知视图,我们可以对每个2D点作出射线,然后沿着射线的方向(即深度方向)做多个点的采样。从下面的动态图获得一个直观感受:
请添加图片描述图4
对于2D图像表示,我们只需要明确像素位置,即可找到对应的颜色值。但对于3D场景表示,我们在某个确定视点看到的2D视图就很难被单一表示出来。因为,确定视点下看到的2D图像是一组图像的加权叠加,而这组图像是你观测视角射线上依次采样出来的,准确来说,2D视图上每一个像素颜色值都是3D场景上在该观测方向的射线上一组采样点的加权叠加。
回头看图(2),先看子图(a),其中黑色的小圆点就是射线上的采样点,每个小圆点就能获得一组9D的训练样本(x,y,z,θ,ϕ ; r,g,b,σ),可直接用来训练MLP。在推理阶段,我们也需要观测射线进行采样。
所以,NeRF是用MLP来隐式表达一个场景,它是点对点的表示方式。我们如果想要获得一个新视角的试图,我们则需要获得这个视角下,观测射线上所有采样点的(r,g,b,σ),假设我们视图的分辨率是224x224的,每个点回引出一条射线(如图2所示),假设每条射线上采样16个点,那我们NeRF中的MLP需要进行224x224x16次推理,得到的结果可以用来进行体渲染。以上是NeRF的基本原理。

2.3、位置编码

位置编码是NeRF中的重要创新点之一,加入位置编码使得NeRF对于新视点重建的效果大大提升。具体效果我们可以看图5。其大概原理是,尽量使相邻位置的输出结果不要相似。每个位置输入X(坐标),经过位置编码以后,与相邻位置具有较大差异。请添加图片描述图5
采用如下公式进行位置编码:
在这里插入图片描述
频率编码,其实是一种广义的傅里叶变换,对于频率位置编码:假设一个位置的x_0=30 ,它相邻的位置是x_1=31,经过r=sin(x∗512)编码以后,x_0编码后的位置为−0.6842,而x_1编码后的位置为0.6240。差距一目了然。这里的512则表示频率,如公式所示的2^(L-1)π。
当然,也如公式所示,我们并不以单一的频率来表示位置编码比如我们挨个用 [1,2,4,8,16,32,64,128,256,512]这10种频率来表示编码位置(只需用公式r=sin(p*x),然后简单concat到一起)。这就完成了基本的位置编码。当然,我们还可以加入相位平移,把cos(p∗x)的结果也concat到一起。
所以,对于一个位置p(x,y,z),我们用10种频率(如[1,2,4,8,16,32,64,128,256,512])来编码,每种频率采用两种相位(sin和cos),那编码后的位置应该有3×10×2=60维来表示原始的三维坐标向量通常,我们会把原始的三维坐标向量也concat到一起,那么就输出60+3=63维,直接喂到MLP里去。
众所周知,NeRF除了位置(x,y,z)输入外,还需要输入观测角度(θ,ϕ)。观测角度可以用ray direction来表示,通常采用三维向量。也需要进行编码,也可以统称为位置编码。我们用同样的方法,但可以少用一些频率,比如我们用[1,2,4,8]这四种频率来编码观测角度。编码后的维度也可计算出来:3×4×2+3=27。

2.4、层次化体采样

原本的体渲染策略并不高效,因为均匀对待每一个采样点。但是空白区域和遮挡区域并没对渲染图像取到作用。作者采用了一种层次化表示来提升渲染效率。具体做法是:采用两个网络来表示一个场景(一个粗,一个细)先用普通采样来评估“粗”网络,然后用“粗”网络来制造更有信息量的采样,比如哪些采样点对体渲染更有帮助
粗采样:在光线上均匀采样,根据体渲染公式获得每个采样点的权重(由体密度和位置远近共同决定);
精采样:根据粗采样获得的权重,做一个光线上的归一化,将权重之和置为1,得到概率密度函数(PDF)。根据PDF来精采样,即让更重要的线段上有更多的采样点
最后,粗采样和精采样的采样点一起进入体渲染,共同作用得到像素的颜色值
s图6

2.5、体渲染

NeRF中最后一个理解难点就是Volume Rendering了,这是一个CG概念。在上面NeRF的训练中,我们得知,NeRF会对每条射线中的每个采样点进行预测,而我们单一新视角的视图中每一个像素点的RGB值需要这一条射线上所有的采样点的(r,g,b,σ)值来决定。而体渲染就是做了这么一件事,它利用了光吸收的物理模型来表达。
如下为体渲染公式:
请添加图片描述
其中,将一条射线的原点标记为o,射线方向(即相机视角)标记为d,则可将射线表示为r(t) = o + td,即距离,积分上下界tf、tn分别是最近和最远的地方。σ是体密度,和距离r(t)有关。c是颜色值,与距离r(t)和方向角d相关。T是光的衰减程度,与物体的不透明度相关。
上公式是连续的理想化公式,如图6所示,一条射线上只有有限的采样点,所以使用离散的方式进行计算。

  • 22
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值