http://www.liuxiao.org/2021/11/%E8%AE%BA%E6%96%87%E7%AC%94%E8%AE%B0%EF%BC%9Anerf-representing-scenes-as-neural-radiance-fields-for-view-synthesis/
https://blog.csdn.net/qq_44324007/article/details/129998545
一、任务描述
- 本文是用NN来做物体/场景的多视角生成的。即,如果我们知道一个物体从多个视角下拍摄的N张图像,我们就可以生成该物体在任何一个视角下的图像。
- 传统的深度学习算法,例如NN的分类算法,我们需要收集大量的各种场景下的多类别图像训练一个模型,然后测试该模型在其他场景下的其他图像的分类性能。而NeRF不一样,nerf是用一个NN模型只overfit一个场景/物体,如果换了场景或者物体,那么你需要重新再训一个NN模型。
- 所以,Nerf其实是一个物体的另一种建模形式,他将一个物体的表征信息压缩在了NN模型(只有MLP)的参数里,这个信息相比较于传统的建模方式(比如mesh, point cloud等)是更加compact的。
二、输入输出
网络结构
扩展多层感知机
多层感知机(multilayer perceptron, MLP) 在单层神经网络的基础上引入了一到多个隐藏层(hidden layer)。隐藏层位于输入层和输出层之间。图3.3展示了一个多层感知机的神经网络图,它含有一个隐藏层,该层中有5个隐藏单元。
3 Optimizing a Neural Radiance Field (优化一个神经辐射场)
上述方法就是 NeRF 的基本内容,但基于此得到的结果并能达到最优效果,存在例如细节不够精细、训练速度较慢等问题。为了进一步提升重建精度和速度,我们还引入了下面两个策略:
- Positional Encoding (位置编码):通过这一策略,能够使得 MLP 更好地表示高频信息,从而得到丰富的细节;
- Hierarchical Sampling Procedure (金字塔采样方案):通过这一策略,能够使得训练过程更高效地采样高频信息。
3.0.网络设计位置和角度分开输入的原因
volume density 透明度是和视角无关的,只和空间中的位置有关系。也就是说如果一个位置上没有物体,那么从任何视角去看,这个位置上都应该是没有物体的。但是color是同时依赖空间位置和视角的。所以模型大概长下面这样。
3.1 Positional Encoding (位置编码)
3.2 Hierarchical Sampling Procedure (分层采样方案)
层采样方案来自于经典渲染算法的加速工作,在前述的体素渲染 (Volume Rendering) 方法中,对于射线上的点如何采样会影响最终的效率,如果采样点过多计算效率太低,采样点过少又不能很好地近似。
那么一个很自然的想法就是希望对于颜色贡献大的点附近采样密集,贡献小的点附近采样稀疏,这样就可以解决问题。
基于这一想法,NeRF 很自然地提出由粗到细的分层采样方案(Coarse to Fine)。
3.3 Implementation Details (实现细节)
第三方库进行 NeRF 的实现
PyTorch 没有直接集成 NeRF,但是可以使用第三方库进行 NeRF 的实现。其中一个比较流行的库是 nerf-pytorch,你可以通过以下命令安装:
pip install nerf-pytorch
安装完成后,你可以使用以下一行代码实现一个简单的 NeRF 模型:
import torch import nerf model = nerf.models.NeRF()
# create model instance
model = NeRF(input_dims=3, output_dims=3)
# generate input data
#生成了一个包含 10 个样本的输入数据 x,每个样本都有 3 个特征。
x = torch.randn(10, 3)
# forward pass
#输出结果 y 的形状是 (10, 4),其中第一维表示有 10 个样本,第二维表示有 4 个特征。
#在 NeRF 中,最后一维通常用于表示颜色或者透明度等信息。
y = model(x)
print(y.shape) # (10, 3)
自行实现
这里定义了一个名为 NeRF 的 PyTorch 模型类,该类接受一个输入维度 input_dims、输出维度 output_dims、隐藏层维度 hidden_dims 和层数 num_layers 等参数。在初始化函数中,我们定义了一个包含多个线性层和 ReLU 激活函数的 MLP 模型。在前向传播函数中,我们使用 MLP 模型对输入数据 x 进行处理,并将输出返回。
import torch from torch import nn from torch.nn import functional as F class NeRF(nn.Module): def __init__(self, input_dims, output_dims, hidden_dims=256, num_layers=8): super().__init__() self.input_dims = input_dims self.output_dims = output_dims # MLP layers layers = [] for i in range(num_layers): layers.append(nn.Linear(input_dims, hidden_dims)) layers.append(nn.ReLU(inplace=True)) input_dims = hidden_dims layers.append(nn.Linear(hidden_dims, output_dims)) self.mlp = nn.Sequential(*layers) def forward(self, x): x = self.mlp(x) # 经过网络层层计算 return x