本文介绍了初代NeRF的训练大致框架。
一、所有深度学习的大致框架
我们看任何一个深度学习代码,都是找这三部分的位置,分析其作用。
最后把 Loss 的梯度更新到 DNN 中,便能不断提高网络的准确度。
二、训练代码的细节
(一)采样区间
首先,作者通过设置 near 和 far 限制了采样区间,如下图所示为 之内。
(二)训练的两个阶段
训练分为两个阶段,会得到 model_courase 和 model_fine 两个模型。
Stage 1 先进行等间距采样,目的是发现密度 较大的点,从而确定下一个阶段的精细采样的“小范围”;Stage 2 在这个小范围内进行精细化采样。
(三)位置编码 positional encoding
一般的 MLP 函数是连续的,因此如果输入的两个 input 点很近(如下图曲线上的蓝色点),那么最终的 output 也会很近。也就是说:一般的 MLP 是没法完成“输入距离很近、输出结果差距却很大”这个任务,但是图像恰巧是这样的任务(相邻位置的像素值差距可能会很大),因此如果直接把坐标 输入到 MLP 中,最后的结果图片是很模糊的(因为没法输出相邻差距很大的结果)。
我们先界定“频率”:(参考Fourier Feature Networks)如果一个点附近都是没有纹理的区域(可以理解成像素值的梯度不大),称为“低频区”,而反之则称为“高频区”。
因此直接输入坐标给 MLP 会导致 DNN 没法学习到“高频”的变化,而通过位置编码,即便两个很近的点,其编码结果也会相差很大(如下图左侧曲线上的黑色点,也就是横轴的坐标差异大),这样一个连续的 MLP 函数也能学到更多的变化。因此频率大小控制的是:可以学习到变化程度多大的图片。
在 NeRF 中,频率不能太小,否则学不到足够的信息;也不能太大,否则会出现过拟合(出现噪点)的现象。NeRF 通过实验发现了合适的值。
代码实现中:如果直接把位置 x 输入到 MLP 得到颜色 c,效果并不好,所以引入positional encoding函数 将位置 x 变成一系列 sin 和 cos 的表达式,如果定义了频率 p,那么总共会到 级别。
在 get_embedder() 中返回位置编码的维度时,有个小细节。这里博主提到:原始论文中引入了 x 作为第一个量,但是后来发现有没有它对结果的影响不大,所以之后就舍去了,但是在看这个初版代码时需要注意这个小细节。
(五)采样点的坐标系变换推导
关于采样点变换坐标的代码如下所示:
下面解释一下上面的变换,其目的是:返回“相机中心”和“像素中心”连线的向量,在世界坐标系下的表示。
那么首先是图像坐标系,坐标原点在左上角,x 轴向右,y 轴向下,然后需要变换到相机坐标系,x 轴仍然保持向右,但是y 轴却变为向上,因此上面的代码中,y 方向的差值算完后又加上了一个负号。
上图所有的单位都是“像素”,包括焦距 focal 的表示,直接除以焦距即可把所有值归一化到“归一化平面”上。并且,相机坐标系的 z 轴和之前的设定是相反的,即从图像中心到相机中心,所以上面代码里 z 的值是 -1 。
接下来就是要把相机坐标系转换到世界坐标系,这个是三维坐标系的刚体变换,如果已知变换矩阵 C2W ,那么只需要把第一步的向量也乘以这个变换矩阵即可变换到世界坐标系下面。代码最后就在做这个相乘的工作。
(四)训练用的像素点采样策略
下图是代码中的 use_batching 的不同策略,区别是采样点来自多张随机图片 or 一张随机图片。
下面这段代码是用来防止 OOM ,让训练继续下去。
原理解释如下图所示:
采样的两个阶段会分别采样 64 和 192 个点,所以一条 ray 上共有 256 个采样点;而每次训练会采样 b=1024 个像素,每个像素都有自己的一条射线,所以共要计算 1024*256 个点。
Question 1: 我们如何知道某个地方有物体呢?每个采样点会通过 MLP 函数计算得到颜色和密度的值,然后可以画出的函数图(如右下角所示),从而就能知道哪些地方会有物体了;对可能有物体的地方再进行 stage 2 即可。
Question 2: 如何避免 OOM 呢?把 1024*256 分成小块 1024*32 进行分批次训练。
(六)如何计算颜色和密度
下面这个公式便是用来计算该像素点最终的颜色 (也就是 DNN 的预测值)。
作者引入了“透明度” 和“采样间隔” 两个变量。我们采用上图中 的公式进行解释会更好些。
“透明度”和“密度” 有关,而密度是个不变的属性,当采样间隔确定时,透明度也是不变的,并且 越大, 越大(无限趋近于 1,这里的 理解成“被遮挡的程度”更恰当些~)。但是因为前面的点会对后面的点产生遮挡关系,因此,比如在计算 对 的影响时,首先是 自己的透明度,然后是 的透明度也会它产生影响,因此最后的效果是这两个量叠加的结果,这个乘积被称为 transmittance ,往后 的结果依此类推即可。
这种计算颜色的方法首先在 DeepView 这种 MPI(Multi Plane Image) 算法中使用到了,它是很多个图层叠加在一起,每个图层的 值不同。
距离 最后的值是 ,代表无限远。
三、延伸
只有颜色和其真值做了 back propogation(做差),而形状并没有,因为实现不知道物体的形状。其他研究,比如 Depth-Supervised NeRF,将 NeRF 输出的 Depth 和用其他方法得到的 Sparse 3D points 做差。
这个方法降低了生成同样效果所需图片的数量,比如从 20 张减少到 3 张,即可得到同样的效果。
标签:采样,框架,代码,像素,MLP,III,坐标系,NeRF From: https://www.cnblogs.com/7ytr5/p/18218283