神经辐射场是一个能表示3D场景的映射,接受3D空间点的坐标
渲染2D图像时,考虑相机发出的一条光线
离散地采样光线上的点之后进行求和,即可计算出像素点颜色的近似值。
如果只在需要求积的区域均匀地采样多个点进行近似计算,可能会导致神经网络只需要学习一系列离散点的信息,从而使得最终生成的结果不够清晰。NeRF采用的是一种分段采样的方法,首先将射线需要积分的区域分为N份,然后在每一个小区域中进行均匀随机采样。这样的方式能够在只采样离散点的前提下,保证采样位置的连续性。
因为射线上的大部分区域,要么被遮挡,要么没有真实物体,对最终的颜色计算没有实际贡献,因此仅仅均匀分段随机采样是有些低效的。NeRF提出一种层次化采样方法,第一阶段粗采样是均匀分段随机采样,第二阶段称为细采样,将粗采样中每个采样点对颜色的贡献权重记为
将
为了使神经网络能够学习到物体的高频信息,提升渲染效果,NeRF采用了一种与Transformer类似的编码方法,即采用正余弦函数变换,具体来说可表示为:
网络结构相对比较简单:多层MLP
原版NeRF采用L2损失作为损失函数,最小化粗采样结果和细采样结果对ground truth的差别,即:
其中$R$为在训练集图像上采样的光线。
InfoNeRF希望在fewshot的条件下,即不需要那么多视角的图片作为训练集的条件下得到相对不错的渲染效果,因此加入了光线的信息熵作为补充信息指导模型训练。信息熵损失扮演一个对射线正则化的角色,避免射线在fewshot条件下过拟合。光线的信息熵定义为:
$$ H(\boldsymbol{r}) = -\sum_{i = 1}^{N} p(\boldsymbol{x}{i}) \log p(\boldsymbol{x}{i}), ;;p(\boldsymbol{x}{i}) = \frac{1 - \exp(-\sigma{i} \delta_{i})}{\sum_{j = 1}^{N} 1 - \exp(-\sigma_{j} \delta_{j})} $$
信息熵较少的光线,几乎没有击中任何物体,因此可以丢弃,即
其中
为保持视角的连续性,InfoNeRF还提出一个平滑损失函数,计算将光线进行一定偏移之后二者的便宜程度,即:
$$ L_{{KL}} := \sum_{i = 1}^{N} p(\boldsymbol{r}{i}) \log \frac{p(\boldsymbol{r}{i})}{p(\tilde{\boldsymbol{r}}_{i})} $$
最终网络用于学习的损失为:
代码的实现参考了mjmjeong/InfoNeRF。
train.py
:实现了与模型训练相关的多个环节,包括参数解析parse_config
、模型的构建create_nerf
、光线粗采样与额外采样、模型保存与测试等。render.py
:实现了与体渲染相关的多个函数,包括给定pose序列生成颜色和时差的render_path
函数,渲染光束对应的颜色图、视差图的render
函数,将神经网络的输出转换为颜色、时差、密度等的raw2outputs
函数等。loss.py
:实现了信息熵损失EntropyLoss
类。NeRF.py
:实现了NeRF神经网络模型。load_blender.py
:实现如何导入数据,生成渲染视频的pose序列。utils.py
:实现位置信息编码函数,以及计算MSE、PSNR、SSIM等的函数。
- OS:
Ubuntu 20.04.5 LTS
- GPU:
NVIDIA GeForce RTX 2080 Ti
- CPU:
Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz
- 内存:128G
python 3.8.15; jittor 1.3.6.10; CUDA 11.0
50000个iter需要训练约4个小时。
在src/
目录下运行以下命令。
python train.py --config lego.txt
模型保存在checkpoints/
目录下。
Iter | Loss | PSNR | 渲染效果 |
---|---|---|---|
20000 | 0.020933 | 16.7914 | |
50000 | 0.015029 | 18.2304 | |
50000 w/o fewshot | 0.001688 | 27.7243 | |
50000 nerf w. fewshot | 0.021349 | 16.5932 |
从渲染结果可以看出,经过50000轮训练,渲染效果相比20000轮训练时要好上很多,但细节上仍然存在不少失真或者模糊的地方,肉眼观测的效果与ground truth相比还是差不少,也比在全部训练集上训练的效果要差的多。然而,这是在仅仅四个视角的图片上训练的InfoNeRF渲染得到的结果,若在无法获得较多视角的照片的情况下,相比普通的NeRF,InfoNeRF具有更佳的性能的。