InstantNGP哈希编码
目录
InstantNGP 主要包括以下三个改进:
- 通过一个更小的 fused MLP 改进了 MLP query 的时间
- 通过 raymatching 和占据网格优化了训练和渲染算法
- 多分辨率的 hash 位置编码算法(主要贡献)
本文主要介绍其中第三点,也就是 hash 位置编码的原理和 nerfstudio 中的具体实现
方法介绍 #
NeRF 对位置的编码 #
原始的 NeRF pipeline 中,位置信息(包括:三维的采样点 $x$ 和三维的方向 $d$)通常被一个位置编码函数编码为高维度的向量,然后输入到 MLP 里进行 RGBA query
这个编码函数在原文中是:
$$ \gamma(p)=(sin(2^0\pi p),cos(2^0\pi p),…,sin(2^{L-1}\pi p),cos(2^{L-1}\pi p)) $$
其中 $p$ 是每个维度的坐标,相当于一个 $R \to R^{2L}$ 的映射,对位置的每个维度都做这样的高维映射
这样做的理由是,作者认为基于过去的经验,MLP 往往倾向于学习低频的特征,而忽视了高频特征,这样的变换能够让原表示中相近的点在高位空间中的距离更远,这样就避免了视角变化小的情况下导致的渲染模糊
InstantNGP 的 Hash 位置编码 #
InstantNGP 中使用了一种可训练的、多分辨率的哈希编码函数,将坐标映射为一组可训练的特征向量,然后在 NeRF 训练过程中优化
位置编码的基本过程:
- 给出一个坐标,找出在 $L$ 分辨率级别中的包围体素,然后哈希这个 grid 的顶点从而得到一个 index(上图 1)
- 使用上述每个 grid 顶点哈希得到的 index 作为 lookup table 的 key 查找一个 $F$ 维的特征向量(这个特征向量是可训练的),然后基于点在 voxel 里的位置,对每个 grid 顶点获得到特征向量进行线性插值,得到这个分辨率下编码的特征向量
- 在 $L$ 级分辨率中每个级别都进行上述操作,将得到的所有长度为 $F$ 的特征拼接到一起,得到大小为 $L\times F$ 的特征
- 之后在把其他的特征加入(上图 3 中长度为 $E$ 的特征),用这组特征输入 MLP 进行 RGBA query
实现 #
InstantNGP 本身是用 C++ 和 CUDA 的 TCNN 框架实现的,后续也有几个工作把这个方法迁移到了 PyTorch 中,并写了 PyTorch CUDA ops 方便使用(包括 torchngp 和 nerfstudio)