由上一章节我们得到了加载到的数据,包括读取图像的数组、图像的高宽焦距、相机的 pose 、以及用于分割测试集、训练集的分割数组。得到这些数据后,我们开始进行生成光线的步骤。
生成光线的步骤是 NeRF 代码中最为关键的一步,实际上我们模拟的光线就是三维空间中在指定方向上的一系列离散的点的坐标。有了这些点坐标,我们将其投入到 NeRF 的 MLP 神经网络中,计算这个点的密度值以及颜色值。
下面我们对具体代码进行分析。
def train():
...
# 加载数据,具体加载代码分析详见 上一篇博客
...
if K is None:
K = np.array([
[focal, 0, 0.5*W],
[0, focal, 0.5*H],
[0, 0, 1]
])
注意这里的 K 。这里的 K 指的是相机的内参,具体的作用会在后面的分析中进行解释说明
1、创建 NeRF 网络模型def train(): ... # 创建 NeRF 网络模型 render_kwargs_train, render_kwargs_test, start, grad_vars, optimizer = create_nerf(args) ...
我们首先对 create_nerf() 返回的值进行解释说明:
render_kwargs_train:一个字典,包含了用于训练的各个参数值。具体字典内容详见下面的代码分析 render_kwargs_test: start: grad_vars: 整个网络的梯度变量 optimizer: 整个网络的优化器
接下来我们对 create_nerf() 代码进行具体的逐行分析:
def create_nerf(args):
embed_fn, input_ch = get_embedder(args.multires, args.i_embed)
...
这行语句实际上获得一个编码器 embed_fn 以及一个编码后的维度,给定 embed_fn 一个输入,就可以获得输入的编码后的数据。具体的编码公式详见论文 5.1 节,代码分析详见:。
以下是网络结构的初始化代码,网络的层级模型详见论文 补充材料 pic 7
def create_nerf(args):
...
# 初始化MLP模型参数,网络的层级模型详见论文 补充材料 pic 7
model = NeRF(D=args.netdepth, W=args.netwidth,
input_ch=input_ch, output_ch=output_ch, skips=skips,
input_ch_views=input_ch_views, use_viewdirs=args.use_viewdirs).to(device)
# 模型中的梯度变量
grad_vars = list(model.parameters())
...
# 定义一个查询点的颜色和密度的匿名函数,实际上给定点坐标,方向,以及查询网络,我们就可以得到该点在该网络下的输出([rgb,alpha])
network_query_fn = lambda inputs, viewdirs, network_fn : run_network(inputs, viewdirs, network_fn,
embed_fn=embed_fn,
embeddirs_fn=embeddirs_fn,
netchunk=args.netchunk # 网络批处理查询点的数量)
今天先更到这里,有时间继续更


