NeRF论文讲解以及公式推导

NeRF论文

  • 传统方法存在的问题

      1. 优化一个表达复杂场景的神经辐射场,存在很难收敛到高分辨率表达的问题
      1. 采样效率低
  • 解决问题的创新点

      1. 将5D坐标和positional encoding一起输入到MLP训练
      1. 使用hierarchical sampling提高采样效率
      1. 新的渲染公式继承了传统体渲染技术可微的特点
  • Pipeline

    • Input
      • 5D coordinates
      • Positional encoding
    • MLP
    • Output
      • color
      • volume density
    • Volume Rendering
    • Rendering Loss

Neural Radiance Field Scene Representation

​ 密度信息 σ \sigma σ仅仅由三维点坐标 x \bold x x进行预测,而颜色信息 c \bold c c允许同时由位置信息 x \bold x x和方向信息 d \bold d d进行预测。

​ 具体的MLP网络结构与上述策略对应。

  • 将位置信息 d \bold d d作为输入过第一个网络,8层全连接层,每一层256通道,使用ReLU函数作为激活函数。此网络输出密度信息 σ \sigma σ,以及一个256维的特征向量
  • 接着,将次特征向量和方向向量 d \bold d d做拼接,作为第二个网络的输入,128通道,ReLU做激活,输出即为颜色信息 c \bold c c

nerf Pytorch版本中的对应如下:
pts_linears: 前八层,得到输出为h

  1. h通过alpha_linear得到体密度1维输出
  2. h和观察视角通过views_linears得到128的输出
  3. 最后得到RGB和σ拼接得到四维输出

Volume Rendering with Radiance Fields

假设前提:发射的光不为观察角度发生改变

因此对于某个视角 o \bold o o发出的方向为 d \bold d d的光线,其在 t \bold t t时刻到达点为: r ( t ) = o + t d \bold r(\bold t)=\bold o+t\bold d r(t)=o+td

那么沿这个方向在范围 ( t n , t f ) (t_n,t_f) (tn,tf)对颜色积分,获得最终的颜色值 C ( r ) C(\bold r) C(r)为:
C ( r ) = ∫ t n t f T ( t ) σ ( r ( t ) ) c ( r ( t ) , d ) d t , w h e r e   T ( t ) = e x p ( ∫ t n t σ ( r ( s ) ) d s ) C(\mathbf{r} ) = \int_{t_n}^{t_f} T(t)\sigma (\bold r(t))\bold c(\bold r(t),\bold d)dt,where \, T(t) = exp(\int_{t_n}^{t}\sigma (\bold r(s))ds) C(r)=tntfT(t)σ(r(t))c(r(t),d)dt,whereT(t)=exp(tntσ(r(s))ds)

函数 T ( t ) T(t) T(t)表示光线从 t n t_n tn t t t累积的透明度 (Accumulated Transmittance)。换句话说,就是光线从 t n t_n tn t t t穿过没有碰到任何粒子的概率。按照这个定义,视图的渲染就是表示成对于 C ( r ) C(\bold r) C(r)​​​​的积分,它是就是虚拟相机穿过每个像素的相机光线,所得到的颜色。

T ( s ) T(s) T(s)​推导过程

σ ( s ) \sigma(s) σ(s)​:在s处,光线碰撞粒子(光线被阻碍)的概率密度

C ( s ) C(s) C(s):在s处粒子发出的颜色

T ( s ) T(s) T(s)​:在特定的一段距离内,光线没有撞击其他粒子的概率

根据 P ( A B ) = P ( A ) P ( B ) P(AB) = P(A)P(B) P(AB)=P(A)P(B) s s s d s ds ds的路程中没有碰到粒子的概率等于 0 − > s 0->s 0>s处没有碰到粒子的概率乘 d s ds ds阶段没有碰到粒子的概率;这两个事件为独立事件,推导如下:
T ( s + d s ) = T ( s ) ( 1 − σ ( s ) d s ) T ( s + d s ) − T ( s ) = − T ( s ) σ ( s ) d s T ′ ( s ) = − σ ( s ) d s T ( s ) = e ∫ 0 t σ ( t ) d t C ^ ( t ) = ∫ 0 + ∞ T ( s ) σ ( s ) c ( s ) d s \\ T(s + ds) = T(s)(1 − \sigma(s)ds) \\T(s + ds) − T(s) = −T(s)\sigma (s)ds \\ T^{'}(s) = −\sigma (s)ds \\ T(s) = e^{\int_{0}^{t}\sigma (t)dt} \\ \hat{C}(t) = \int_0 ^{+\infin} T(s) \sigma(s)c(s)ds T(s+ds)=T(s)(1σ(s)ds)T(s+ds)T(s)=T(s)σ(s)dsT(s)=σ(s)dsT(s)=e0tσ(t)dtC^(t)=0+T(s)σ(s)c(s)ds

不过在实际的渲染中,我们并不能进行连续积分,因为计算机只能处理离散数据,我们使用求积法(quadrature)进行积分的数值求解。 通过采用分层采样 (stratified sampling) 的方式对 [ t n , t f ] [t_n,t_f] [tn,tf]划分成均匀分布的小区间,对每个区间进行均匀采样,划分的方式如下:
t i ∼ U [ t n + i − 1 N ( t f − t n ) , t n + i N ( t f − t n ) ] t_{i} \sim \mathcal{U}\left[t_{n}+\frac{i-1}{N}\left(t_{f}-t_{n}\right), t_{n}+\frac{i}{N}\left(t_{f}-t_{n}\right)\right]

### NeRF 论文详解及其实现教程 #### 基本概念 NeRF (Neural Radiance Fields) 是一种用于视图合成的技术,能够通过对场景的多角度图像进行建模,在未观察到的角度上生成高质量的新视图。其核心思想是将连续的体积密度和辐射度表示为神经网络的隐函数[^1]。 具体而言,NeRF 使用 MLP(多层感知机)来学习一个从空间位置 \( \mathbf{x} \in \mathbb{R}^3 \) 和观测方向 \( \mathbf{d} \in \mathbb{S}^2 \) 到颜色 \( \mathbf{c}(\mathbf{x},\mathbf{d}) \) 和体积密度 \( \sigma(\mathbf{x}) \) 的映射关系。这种设计使得 NeRF 能够捕捉复杂的几何结构和外观细节[^2]。 #### 实现流程概述 为了复现实现 NeRF,通常需要以下几个主要步骤: 1. **数据准备**: 收集一组目标物体或多视角场景的照片,并记录相机参数(如内在矩阵、外在矩阵等)。这一步可以通过 COLMAP 或其他 SfM 工具完成。 2. **模型定义**: 定义两个嵌套的 MLP 结构——粗略采样阶段和精细采样阶段。前者负责快速估计场景的大致分布,后者则进一步优化光线上的样本点以提高精度[^3]。 3. **前向传播计算**: 对于每条光线,执行分步积分操作,结合采样的位置信息与方向信息预测最终像素的颜色值。 4. **损失函数构建**: 主要采用 MSE Loss 来衡量预测图像与真实图像之间的差异。此外还可以加入正则化项防止过拟合等问题发生。 5. **训练过程管理**: 设置合适的超参并监控指标变化趋势直至收敛为止。 以下是基于 PyTorch 的简单代码框架展示如何搭建基础版 NeRF 模型: ```python import torch from torch import nn class BasicMLP(nn.Module): def __init__(self, input_dim=3, hidden_dim=256, output_dim=4): super(BasicMLP, self).__init__() layers = [] for _ in range(8): # Define depth of network here. layers.append(nn.Linear(input_dim if not layers else hidden_dim, hidden_dim)) layers.append(nn.ReLU()) self.mlp_network = nn.Sequential(*layers, nn.Linear(hidden_dim, output_dim)) def forward(self, x): return self.mlp_network(x) def render_rays(ray_batch, model_coarse, model_fine=None): """Render rays by computing the output colors given a model.""" N_rand = ray_batch.shape[0] z_vals = ... # Sample points along each ray according to some strategy. pts = ... # Compute point locations based on sampled distances and origins/directions from `ray_batch`. raw_coarse = model_coarse(pts.view(-1,pts.size(-1))).view(N_rand,-1,model_coarse.output_dim) rgb_map_coarse, weights = volume_rendering(raw_coarse[..., :3], raw_coarse[..., -1:], z_vals=z_vals) if model_fine is None: return {'rgb': rgb_map_coarse} fine_z_vals = sample_pdf(z_vals, weights[:, :-1].detach(), N_importance).detach() fine_points = get_ray_points_from_zvals(...) raw_fine = model_fine(fine_points.reshape(-1,fine_points.size(-1))) rgb_map_fine = ... outputs = { 'rgb_coarse': rgb_map_coarse, 'rgb_fine': rgb_map_fine} return outputs ``` 以上仅为简化版本示意用途,请参照官方仓库链接获取更完整的源码文件。 --- #### 当前研究进展中的挑战与发展 尽管 NeRF 取得了显著成就,但在实际应用场景下仍存在诸多局限性。例如当面对动态对象或者大规模户外环境时表现不佳;另外长时间耗损较大的计算资源也是亟待解决的问题之一[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值