前言

  本文介绍Volumetric Rendering与NeRF。

Volumetric Rendering

以下关于Volumetric Rendering与几篇原论文在表述上略有区别,不过最终结论是一致的~

假设

  体渲染(Volumetric Rendering)对(人眼、相机)成像进行了解构理解。对于相机在某一位置$\boldsymbol o\in\mathbb R^3$渲染得到的图片$\{\boldsymbol C=(r,g,b) \},\;\boldsymbol C\in\{0,\cdots,255\}^3$,任意两像素$\boldsymbol C_i$与$\boldsymbol C_j$的渲染过程无关。此外,对于任意三维物体(主要是Scene),认为是其由无数微小的以太粒子构成的体积云。粒子属性除位置信息$\boldsymbol x=(x,y,z)\in\mathbb R^3$外,还具有颜色信息$\boldsymbol c(\boldsymbol x, \boldsymbol d)\in\{0,\cdots,255 \}^3$,其中$\boldsymbol d$为观察角度。

思路

  令渲染得到的图像在相机与体积云连线的无穷远处。对于图像的任一像素,我们认为其是由相机光心到像素处的一条辐射线(Ray)渲染得到。从光心开始,辐射线将顺序途径若干以太粒子,每个粒子都有一定概率吸收该辐射线以贡献自身的颜色信息。将这条辐射线途径的所有粒子的颜色信息期望叠加作为最终的像素颜色。

![Volumetric Rendering (Source: [1])](https://hjhgjghhg-1304275113.cos.ap-shanghai.myqcloud.com/usr/img/3D%20Multiple%20Views%20Synthesis%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9ANeRF/v2-51b9f7faf537c7899a5188eba16ec583_1440w.webp)

刻画

  下面我们从数学的角度刻画这一渲染过程。对于像素$\boldsymbol C$,记光心到该像素的单位向量为$\boldsymbol d$,则$\boldsymbol C$对应的辐射线为$\boldsymbol r(t)=\boldsymbol o+t\boldsymbol d,t\geq 0$。假设在$\boldsymbol x(t)=\boldsymbol r(t)$处的粒子吸收辐射线的微分概率为$\sigma(\boldsymbol x)\in [0,1]$,则辐射线再经过$\text d \boldsymbol r$被吸收的概率为$\sigma(\boldsymbol x)\text d\boldsymbol x$。又设辐射线在$\boldsymbol x$处仍未被吸收的概率为$T(\boldsymbol x)$。由于两个事件:“从$\boldsymbol 0$到$ \boldsymbol x$辐射线未被吸收”与“从$\boldsymbol x$到$\boldsymbol x+\text d\boldsymbol x$辐射线未被吸收”相互独立,则:

$$ T(\boldsymbol x+\text d\boldsymbol x)=T(\boldsymbol x)\cdot\Big(1-\sigma(\boldsymbol x)\text d\boldsymbol x \Big)\tag{1} $$

容易知道:$T(\boldsymbol 0)=1,T(+\infty)=0$,则解该微分方程:

$$ T(\boldsymbol x)=\exp\left(-\int_{0}^\boldsymbol x \sigma(\boldsymbol u)\text du \right)\tag{2} $$

  考虑事件:“辐射线终止于$\boldsymbol r+\text d\boldsymbol r$处”,其可以分成两个相互独立的事件:“从$\boldsymbol 0$到$\boldsymbol r$辐射线未被吸收”与“从$\boldsymbol r$到$\boldsymbol r+\text d\boldsymbol r$辐射线被吸收”。总体概率为:$T(\boldsymbol r)\cdot \sigma(\boldsymbol r)\text d\boldsymbol r$。此时$\boldsymbol r$处的粒子贡献其颜色信息$\boldsymbol c(\boldsymbol r,\boldsymbol d)$。因此最终像素$ \boldsymbol C$处的颜色期望为:

$$ \mathbb E[\boldsymbol C(\boldsymbol r)]=\int_{\boldsymbol 0}^{+\infty}T(\boldsymbol r)\cdot \sigma(\boldsymbol r)\cdot \boldsymbol c(\boldsymbol r, \boldsymbol d)\text d\boldsymbol r=\int_0^{\infty} T(\boldsymbol r(t))\cdot\sigma(\boldsymbol r(t))\cdot \boldsymbol c(\boldsymbol r(t), \boldsymbol d)\text dt\tag{3} $$

离散

  当然实际使用中我们会选取两个点$t_n$(near)与$t_f$(far)作定积分,此外我们还需要将积分化为求和。为了简便计算,首先将$[t_n,t_f]$均分为$N$段,再从这$N$个小区间中取$N$个$t_i$:

$$ t_i\sim \mathcal U\left[t_n+\frac{t_f-t_n}{N}\cdot(i-1) ,t_n+\frac{t_f-t_n}{N}\cdot i\right],\quad i\in\{0,c\cdots, N \}\tag{4} $$

记$\delta_i=t_{i+1}-t_i$。当$N\to \infty$,$t_i$到$t_{i+1}$之间的颜色与吸收概率均可视为常数,唯一需要处理的是$T(t_i)$。则$t_i$处的颜色期望为:

$$ \begin{align} \mathbb E[\boldsymbol C(\boldsymbol r)]_i&=\int_{t_i}^{t_{i+1}}T(\boldsymbol r(t_i))\cdot\sigma(\boldsymbol r(t_i))\cdot \boldsymbol c(\boldsymbol r(t_i),\boldsymbol d)\text dt\\ &=\sigma_i\boldsymbol c_i\int_{t_i}^{t_{i+1}}\exp\left(-\int_{t_n}^{t} \sigma(\boldsymbol r(u))\text du \right)\text dt\\ &=\sigma_i\boldsymbol c_i\cdot T(\boldsymbol r(t_i))\int_{t_i}^{t_{i+1}}\exp\left(-\int_{{\color{Red}t_i}}^{t}\sigma(\boldsymbol r(u))\text du \right)\text dt\\ &\approx \sigma_i\boldsymbol c_i\cdot T(\boldsymbol r(t_i))\int_{t_i}^{t_{i+1}}\exp\left(-\sigma_i(t-t_i) \right)\text dt\\ &=\sigma_i\boldsymbol c_i\cdot T(\boldsymbol r(t_i))\cdot\left.\frac{e^{-\sigma_i(t-t_i)}}{-\sigma_i}\right|_{t_i}^{t_{i+1}}\\ &=T(\boldsymbol r(t_i))\cdot\boldsymbol c_i(1-e^{-\sigma_i\delta_i}) \end{align}\tag{5} $$

  其中$\boldsymbol c_i=\boldsymbol c(\boldsymbol r(t_i),\boldsymbol d),\;\sigma_i=\sigma(\boldsymbol r(t_i))$。当然对于$T(\boldsymbol r(t_i))$,也需要进行离散化:

$$ T_i\overset{\text{def}}{=}T(\boldsymbol r(t_i))\approx \exp\left(-\sum_{j=1}^{i-1}\sigma_j\delta_j\right)\tag{6} $$

  所以最终的颜色期望:

$$ \mathbb E[\boldsymbol C(\boldsymbol r)]=\sum_{i=1}^N\mathbb E[\boldsymbol C(\boldsymbol r)]_i=T_i\cdot\boldsymbol c_i(1-e^{-\sigma_i\delta_i})\tag{7} $$

NeRF

  现在我们可以来研究NeRF了。我们需要基于(7)进行Volumetric Rendering,其中未知量为$\sigma_i$与$\boldsymbol c_i$,那么自然神经网络的输出便是$\boldsymbol c$与$\sigma$。而又由于针对的问题为Multiple Views Synthesis,需要区别输入的多张图片,NeRF为此显式地加入了相机旋转角(也即辐射线方向$\boldsymbol d$的两个自由度):$\theta,\varphi$。加上相机位置$\boldsymbol x=(x,y,z)$一共五维$(x,y,z,\theta,\varphi)$作为输入。最后简单弄一个MLP即可:

$$ F_{\boldsymbol\Theta}:(x,y,z,\theta,\varphi)\to(\boldsymbol c,\sigma)\tag{8} $$

  再通过(7)式渲染得到predict,最后选一个loss就完成了该场景的渲染啦~值得注意的是,$F_{\boldsymbol \Theta}$保存的是单个场景的神经隐式表达,不像其他模型具有泛化能力。
  事实上这还不够,仅用MLP学习隐式表达渲染结果较差,作者还额外提出了两个提点trick:Positional encoding与Hierarchical volume sampling。

Positional encoding

  看到Positional encoding大家或许会立刻想到Transformer中捕捉序列位置关系的Positional embedding,事实上只是形式上相似,出发点完全不同,因此我们先暂时忘记Transformer中的位置编码。
  作者从18年Bengio组的一篇文章中得到启发:

...having the network $F_{\boldsymbol\Theta}$ directly operate on $xyz\theta\varphi$ input coordinates results in renderings that perform poorly at representing high-frequencyvariation in color and geometry. ...deep networks are biased towards learning lower frequency functions.

因此使用纯MLP难以捕捉颜色等高频信息,因此作者采用类似于傅里叶变换的Positional encoding将低维输入映射到高维空间,从而提升网络捕捉高频信息的能力。具体地对输入的每一维分量$p$:

$$ \gamma(p)=\left(\sin \left(2^{0} \pi p\right), \cos \left(2^{0} \pi p\right), \cdots, \sin \left(2^{L-1} \pi p\right), \cos \left(2^{L-1} \pi p\right)\right)\tag{9} $$

Hierarchical volume sampling

  解决完高频信息捕捉后我们再来考虑另一个问题。我们是通过采样$N$个点完成积分的离散化计算,但$N$的取值难以确定:采样点过多开销过大,采样点过少近似误差有太大。直观的一个想法是,最好尽可能的避免在空缺部分以及被遮挡了的部分进行过多的采样,因为这些部分对最好的颜色贡献很少。

  那么如何采样效率最高呢?最直观的想法是多采几次:Nerf使用两个网络同时进行训练 (后称coarse和fine网络), coarse作为粗粒度采样,均匀在Ray上采出$N_c$个点,根据coars网络对光线的分布进行估计:

$$ \mathbb E[\boldsymbol C(\boldsymbol r)]_{c}=\sum_{i=1}^{N_{c}} w_{i} \boldsymbol c_{i}, \quad w_{i}=T_{i}\left(1-e^{-\sigma_{i} \delta_{i}}\right)\tag{10} $$

  归一化的$w_i$可以视作光线在$\boldsymbol r$上的分段PDF,再通过逆分布采样从该分布中取出$N_f$个点,然后再把所有的采样点一起输入到fine网络进行预测。具体过程请见下图:

![Hierarchical volume sampling (Source: [2])](https://hjhgjghhg-1304275113.cos.ap-shanghai.myqcloud.com/usr/img/3D%20Multiple%20Views%20Synthesis%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9ANeRF/v2-9b201c3324684526396afb03aa0e42d5_1440w.webp)

总结

  最后我们总结一下NeRF。其针对的任务为Novel View Synthesis(或者说Multiple Views Synthesis):在已知视角下对场景进行一系列的捕获 (包括拍摄到的图像,以及每张图像对应的内外参),不需要中间三维重建的过程,仅根据位姿内参和图像,合成新视角下的图像。而后先将这些位置输入MLP以产生volume density($\sigma$)和RGB颜色值($\boldsymbol c$);取不同的位置,使用Volumetric Rendering将这些值合成为一张完整的图像;由于Volumetric Rendering可微,所以可通过最小化上一步渲染合成的、真实图像之间的loss来训练优化NeRF场景表示。最后再给定$(x,y,z,\theta,\varphi)$渲染出新视角下的图片。

![NeRF (Source: [3])](https://hjhgjghhg-1304275113.cos.ap-shanghai.myqcloud.com/usr/img/3D%20Multiple%20Views%20Synthesis%EF%BC%88%E4%B8%80%EF%BC%89%EF%BC%9ANeRF/NeRF.png)

  NeRF的原理已经介绍完毕了,下面我们将介绍NeRF的PyTorch实现。

References

  1. “图形学小白”友好的NeRF原理透彻讲解
  2. 尽量简单易懂的讲清楚神经辐射场(Nerf)
  3. NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis, ECCV 2020 -NeRF
    Ben Mildenhall, Pratul P. Srinivasan, Matthew Tancik, Jonathan T. Barron, Ravi Ramamoorthi, Ren Ng, 2020.3 | [[ECCV pdf]](https://www.ecva.net/papers/eccv_2020/papers_ECCV/papers/123460392.pdf) [[arXiv pdf]](https://arxiv.org/pdf/2003.08934.pdf) [[Project homepage]](https://www.matthewtancik.com/nerf) [[Official implementation (TF)]](https://github.com/bmild/nerf)
如果觉得我的文章对你有用,请随意赞赏