NeRF入门学习笔记一
NeRF 全称是 Neural Radiance Field (神经辐射场),它是想做这样一件事情:
给定一个场景,输入相机 (或者观察者) 的位置和观察视角后,输出这个视角下的视图
NeRF可以简要概括为用一个MLP(全连层而非卷积,加上激活层)神经网络去隐式地学习一个静态3D场景,实现复杂场景的任意新视角合成(渲染)。
为了训练网络,针对一个静态场景,需要提供包含大量相机参数已知的图片的训练集,以及图片对应的相机所处3D坐标,相机朝向(2D,但实际使用3D单位向量表示方向)。
一些文章相关的链接:
链接1: https://blog.csdn.net/qq_45752541/article/details/130072505
链接2: https://zhuanlan.zhihu.com/p/628676557
体渲染
通常会在每条光路上采样一些点,由这些采样点上的粒子来代表整条光线。最终每条光线渲染出来的颜色值都可以用下面的公式表示:
在传统的计算机图形学中,我们需要先知道整个场景中,每条光线上的每个采样点的粒子状态 (也就是每个采样点处粒子的密度),才能渲染出整个画面。NeRF 就是用来计算这些数值的。
NeRF(神经辐射场)
介绍
NeRF 中,让神经网络自己去学出来体渲染中这些粒子状态。
过程是这样的:
给定相机位置和朝向后,我们可以确定出当前的成像平面。然后,将相机的位置坐标和平面上的某个像素相连,就确定了一条光线 (也即确定了光线的方向)。接着用网络预测出光线上每个采样点的粒子信息,就可以确定像素颜色。这个过程重复下去,直到每个像素都渲染完为止。
这些排列整齐的光线,构成了类似磁场一样的东西,而光线本身就是一种辐射,因此叫辐射场。而每条光线上的粒子信息又都是由神经网络预测的,因此作者又给整个过程命名为神经辐射场。
算法训练流程
- 选择一个特定的场景 。
- 在这个场景的四周摆放一些相机,并确定好相机位置
和光线方向。 - 沿着光线方向乘以不同的采样距离,可以确定光线上每个采样点的位置。注意,此时每个采样点对应的方向向量会转换成笛卡尔坐标系 。
- 将相机位置以及方向向量送入网络后,让网络预测出光线上采样点的粒子信息,根据公式 (3) 渲染出整个画面。
- 将模型渲染的结果和相机捕捉的真实结果计算损失 (均方误差),由于公式 (3) 是可导的,因此梯度可以正常回传,从而训练整个网络。
网络结构
NeRF 的网络结构是一个很简单的全连接网络。
作者把密度和颜色分为两部分输出,这么做的考量在于,粒子密度是跟三维场景本身更强相关的属性,不管观察的方向怎么变,它都不会有太大的变化 (即论文中提到的 multiview consistent),而颜色值在不同观察方向下,受光照影响,可能会发生大的变动,它受相机位置和观察方向的影响都更大。
相关技术原理
位置信息编码(Positional encoding)
由于 (x, y, z)这类位置和方向向量只有三维,如果直接将它们投喂给网络,那网络也只能回馈给你低维度的信号,而如果能把输入拓展成更高维,那网络的输出信号会包含更高维的信息,图像内容会更丰富,图像质量更高。
使用位置信息编码的方式将输入先映射到高频(高维)可以有效地解决这个问题。论文中使用的是正余弦周期函数的形式:
位置和视角先进行归一化,到[-1,1]之间。对于位置向量 , γ(x)设置 L=10, 即每个元素会拓展成 20 维,输入是 60 维的向量。位置向量γ(d)设置 L=4, 则是 24 维 (3*8)。
层次采样 (hierarchical sampling)
前面提到,NeRF 会对每根光线进行采样,然后用网络对每个采样点进行预测。而由于资源的限制,采样不可能做到很密集。
因此,在密度高的地方多放一些采样点是比较合适的,即做 importance sampling。论文为此设计了一种“coarse to fine”由粗到细的分层采样方法,同时优化coarse和fine两个网络。思路如下:
-
首先是粗粒度采样。先在每条光线上均匀采样Nc个点,让coarse网络预测出这些点的粒子密度。改写上述体渲染的公式
这里的 ωi 是归一化后的 ,可以看作是沿着射线方向的概率密度函数,我们可以粗略地得到射线方向上物体的分布情况。 -
根据这些密度信息,使用逆变换采样(inverse transform sampling)方法,重新在密度更高的采样点附近采样Nf个密集点,然后在Nc+Nf的采样点集合上,计算refine网络的渲染结果。
-
两轮预测的结果分别计算 loss。
优缺点总结:
渲染出来的图像清晰度更高,但是渲染速度极其慢。
泛化性很差,针对不同的场景,需要进行独立训练一个NeRF。
总结
NeRF 可以预测三维场景中每个视角的二维投影信息,因此,它本身也具备了整个三维场景的信息,可以认为是一种三维重建算法。
但是,这个神经网络只建立了观察视角与三维模型之间的映射,给你对应视角下三维场景的二维投影。
因此,后续继续学习利用 SDFNetwork 和 RenderingNetwork 合成真正三维模型。