深入理解神经辐射场 (NeRF):从体渲染到可微 3D 重建

4014 字
20 分钟
深入理解神经辐射场 (NeRF):从体渲染到可微 3D 重建

1. 引言:神经渲染的范式革命#

1.1 什么是 NeRF?#

神经辐射场(Neural Radiance Fields,NeRF) 是 Mildenhall 等人在 2020 年 ECCV 上提出的革命性方法,论文标题为 “Representing Scenes as Neural Radiance Fields for View Synthesis”

它的核心思想令人惊艳:

用一个简单的多层感知机(MLP)作为”场景记忆器”,输入空间坐标和观察方向,输出颜色与密度;通过对相机光线进行体渲染积分,即可从任意新视角合成出照片级真实感的图像。

这种”神经网络即场景”的表示方法,绕过了传统几何重建(点云、网格)的中间步骤,直接从图像端到端学习场景的连续表征。

1.2 为什么 NeRF 重要?#

维度传统方法NeRF
表示离散(点云 / 体素 / Mesh)连续(MLP 隐式表示)
渲染质量受网格分辨率限制照片级真实感
几何表达需要显式重建隐式学习
新视角合成依赖纹理映射任意视角生成
存储效率高分辨率 Mesh 庞大单个 MLP 仅 ~5MB

NeRF 开启了神经隐式表示这一研究范式,并催生了 Instant-NGP、Plenoxels、Mip-NeRF 360、3D Gaussian Splatting 等一系列后续工作。

1.3 NeRF 的应用场景#

  • 电影 / 特效:自由视角视频(Free-Viewpoint Video)
  • VR / AR:沉浸式三维内容生成
  • 文化遗产:文物、遗址的高保真数字化
  • 自动驾驶:场景重建与仿真
  • 机器人:环境建模、避障
  • 医学影像:CT / MRI 三维重建
  • 数字人:人脸 / 人体 NeRF 重建

2. 核心思想:5D 神经辐射场#

2.1 场景的数学建模#

NeRF 把一个静态场景建模为一个 5D 向量值函数

Fθ:(x,d)(c,σ)F_\theta: (\mathbf{x}, \mathbf{d}) \rightarrow (\mathbf{c}, \sigma)

其中:

  • x=(x,y,z)R3\mathbf{x} = (x, y, z) \in \mathbb{R}^3空间位置(3D 坐标)
  • d=(θ,ϕ)S2\mathbf{d} = (\theta, \phi) \in \mathbb{S}^2观察方向(单位向量)
  • c=(r,g,b)R3\mathbf{c} = (r, g, b) \in \mathbb{R}^3该位置沿方向 d\mathbf{d} 观察到的颜色
  • σR+\sigma \in \mathbb{R}^+体积密度(Volume Density),表示该位置的”不透明度”

关键洞察:颜色是视角相关的(镜面反射),但密度是视角无关的(几何属性)。NeRF 显式地分离这两者。

2.2 为什么需要视角依赖?#

考虑一个金属球

  • 正面看:能看到球面的高光(接近白色)
  • 侧面看:看到的是漫反射(接近灰色)
  • 但球的位置和密度始终不变

如果颜色只依赖于位置,就只能表达漫反射;引入方向后,可以表达视角相关效果(镜面反射、各向异性等),这是高质量渲染的关键。

2.3 MLP 结构#

FθF_\theta 用一个简单的 MLP 实现,约 8 层全连接,宽度 256:

输入: x = (x, y, z) → γ(x) (位置编码, 详见第 4 节)
8 层 MLP
临时特征: z(x) (输出 256 维)
┌───────┴────────┐
↓ ↓
σ ← Linear(z) c ← concat(z, γ(d)) → 额外 MLP → Linear → RGB
(1 维) (128 维中间层)

注意:密度 σ\sigma 只从位置特征 γ(x)\gamma(\mathbf{x}) 预测;颜色 c\mathbf{c} 则结合位置特征 γ(d)\gamma(\mathbf{d}) 和方向编码 γ(d)\gamma(\mathbf{d}) 共同预测。

设计巧思:这种结构强制 MLP 先用位置信息判断”这是不是一个表面”,再用方向信息判断”沿这个方向看是什么颜色”——这符合物理直觉。

3. 体渲染:从辐射场到 2D 图像#

3.1 物理模型:光线的辐射积分#

在真实世界中,从相机出发的每条光线都会与场景中的物质发生吸收、发射、散射。最终到达相机的颜色,是沿光线对所有辐射贡献的加权积分。

NeRF 假设场景中没有散射(即只吸收和发射),那么颜色可由下式给出:

C(r)=tntfT(t)σ(r(t))c(r(t),d)dtC(\mathbf{r}) = \int_{t_n}^{t_f} T(t) \, \sigma(\mathbf{r}(t)) \, \mathbf{c}(\mathbf{r}(t), \mathbf{d}) \, dt

其中:

  • r(t)=o+td\mathbf{r}(t) = \mathbf{o} + t\mathbf{d}:光线的参数化方程
  • T(t)T(t):累积透射率(光线从 tnt_n 走到 tt 而未被吸收的比例)
  • σ()\sigma(\cdot):体密度函数
  • c()\mathbf{c}(\cdot):辐射颜色
  • tn,tft_n, t_f:近端 / 远端距离

累积透射率定义为:

T(t)=exp(tntσ(r(s))ds)T(t) = \exp\left( - \int_{t_n}^{t} \sigma(\mathbf{r}(s)) \, ds \right)

直观理解T(t)T(t) 表示”光线到达 tt 之前有多大概率没被任何东西挡住”。

3.2 离散化:数值积分#

连续积分无法直接用神经网络计算,需要离散化为分层采样

C^(r)=i=1NTi(1exp(σiδi))ci\hat{C}(\mathbf{r}) = \sum_{i=1}^{N} T_i \, (1 - \exp(-\sigma_i \delta_i)) \, \mathbf{c}_i

其中:

  • NN:采样点数量
  • δi=ti+1ti\delta_i = t_{i+1} - t_i:相邻采样点的距离
  • αi=1exp(σiδi)\alpha_i = 1 - \exp(-\sigma_i \delta_i):该采样点的不透明度
  • Ti=j=1i1(1αj)T_i = \prod_{j=1}^{i-1}(1 - \alpha_j):累积透射率

3.3 体积渲染流程图#

相机射线 r = o + td
┌────┴────┐
↓ ↓
采样 采样
↓ ↓
σ₁,c₁ σ₂,c₂ ... σₙ,cₙ
↓ ↓ ↓
──→ α₁ α₂ αₙ (αᵢ = 1 - exp(-σᵢδᵢ))
↓ ↓ ↓
T₁·α₁·c₁ + T₂·α₂·c₂ + ... + Tₙ·αₙ·cₙ
像素颜色 C(r)

3.4 代码实现#

import torch
def volume_render(sigmas, colors, deltas):
"""
sigmas: (N_samples,) 体密度
colors: (N_samples, 3) 颜色
deltas: (N_samples,) 相邻采样点距离
"""
# 计算每段的不透明度 alpha
alphas = 1.0 - torch.exp(-sigmas * deltas)
# 累积透射率 T
Ts = torch.cumprod(1.0 - alphas + 1e-10, dim=0)
# 注意:T[0] = 1(从近端开始),T[i] 对应 i 之前未被吸收的比例
Ts = torch.cat([torch.ones_like(Ts[:1]), Ts[:-1]], dim=0)
# 加权求和
weights = Ts * alphas # (N,)
pixel_color = (weights.unsqueeze(-1) * colors).sum(dim=0)
return pixel_color, weights

4. 位置编码(Positional Encoding)#

4.1 为什么需要位置编码?#

深度学习的一个普遍现象:MLP 倾向于学习低频函数。对于类似 (x,y,z)(x, y, z) 这种 3D 坐标,MLP 难以表达锐利的边缘和精细细节。

位置编码(Positional Encoding, PE)的灵感来自 Transformer:将低维输入通过高频函数映射到高维空间,让 MLP 能拟合高频变化。

4.2 编码公式#

对于标量坐标 p\mathbf{p}(如 xx),其位置编码为:

γ(p)=(sin(20πp),cos(20πp),,sin(2L1πp),cos(2L1πp))\gamma(\mathbf{p}) = \left( \sin(2^0 \pi \mathbf{p}), \cos(2^0 \pi \mathbf{p}), \ldots, \sin(2^{L-1} \pi \mathbf{p}), \cos(2^{L-1} \pi \mathbf{p}) \right)

其中 LL 是编码阶数(NeRF 原始论文中 L=10L=10 用于位置,L=4L=4 用于方向)。

为什么是 2 的幂次?这是为了让编码覆盖从粗到细的频率范围。

4.3 代码实现#

def positional_encoding(x, L):
"""
x: (..., D) D 维输入
L: 编码阶数
return: (..., D * 2 * L)
"""
freqs = (2.0 ** torch.arange(L, device=x.device)) * torch.pi
# x: (..., D) → (..., D, 1)
# freqs: (L,) → (..., 1, L)
xb = x.unsqueeze(-1) * freqs
return torch.cat([torch.sin(xb), torch.cos(xb)], dim=-1).flatten(-2)

4.4 频率选择的影响#

阶数 LL编码维度表达范围
L=1L = 16仅最粗粒度
L=5L = 530中等细节
L=10L = 1060NeRF 默认,丰富细节
L=15L = 1590极高细节(但易过拟合)

如果 LL 太小:图像会非常平滑、模糊 如果 LL 太大:会出现高频噪声、过拟合

5. 训练流程#

5.1 训练数据准备#

NeRF 的训练数据要求比较严格:

  1. 多视角图像:同一场景的多张图像(通常 50~200 张),且视角需有足够变化
  2. 相机标定:每张图像对应的相机内外参(内参 KK、外参 [Rt][\mathbf{R}|\mathbf{t}]
  3. 相机位姿估计:通常用 COLMAP 通过 SfM(Structure from Motion)自动恢复

没有精确的相机位姿,NeRF 无法训练。这是它最大的”门槛”之一。

5.2 训练过程#

输入:图像集 {Ii}\{\mathbf{I}_i\} 与相机位姿 {πi}\{\boldsymbol{\pi}_i\}

目标:优化 MLP 参数 θ\theta

for iteration in range(num_iters):
1. 随机采样一批相机视角
2. 对每个像素,生成相机射线 r = o + td
3. 在光线上分层采样 N 个点
4. 用 MLP 预测 (σ, c) 在每个点
5. 体渲染得到预测像素颜色 Ĉ
6. 计算损失 L = Σ ||Ĉ - C_gt||²
7. 反向传播更新 θ

5.3 损失函数#

原始 NeRF 使用简单的 MSE 损失

L=rRC^(r)Cgt(r)22\mathcal{L} = \sum_{\mathbf{r} \in \mathcal{R}} \left\| \hat{C}(\mathbf{r}) - C_{\text{gt}}(\mathbf{r}) \right\|_2^2

其中 R\mathcal{R} 是一个 batch 中随机采样的光线集合。

后续工作(如 Mip-NeRF 360)加入了 LPIPS、SSIM 等感知损失,进一步提升质量。

5.4 分层采样(Hierarchical Sampling)#

NeRF 的一个关键技巧:粗采样 + 细采样 两阶段:

第一阶段(粗采样):
在光线上均匀采样 N_c 个点(如 64)
用这些点的权重分布得到粗略的密度分布
第二阶段(细采样):
根据粗采样的权重分布,用逆变换采样 N_f 个点(如 128)
这些点集中在"重要"区域(接近表面的位置)
最终渲染:合并所有点(粗 + 细)一起做体渲染

这种策略让采样点集中在真实表面附近,大幅减少冗余计算,并提升渲染质量。

5.5 训练时间与资源#

配置训练时间显存
单 RTX 3090~24 小时~10 GB
单 RTX 4090~12 小时~10 GB
Google TPU v2~10 小时TPU 内存
Instant-NGP (哈希加速)~5 分钟~4 GB

原始 NeRF 极其缓慢——这是它最大的实用瓶颈,催生了大量加速研究。

6. 完整代码示例:PyTorch 简化版#

6.1 模型定义#

import torch
import torch.nn as nn
class NeRF(nn.Module):
def __init__(self, pos_L=10, dir_L=4, hidden=256):
super().__init__()
self.pos_L, self.dir_L = pos_L, dir_L
# 位置编码维度: 3 * 2 * pos_L
# 方向编码维度: 3 * 2 * dir_L
self.in_dim_pos = 3 + 3 * 2 * pos_L
self.in_dim_dir = 3 + 3 * 2 * dir_L
# 主干 MLP (8 层)
self.backbone = nn.Sequential(
nn.Linear(self.in_dim_pos, hidden), nn.ReLU(),
*[nn.Sequential(nn.Linear(hidden, hidden), nn.ReLU()) for _ in range(7)]
)
# 密度分支
self.sigma_head = nn.Linear(hidden, 1)
# 中间特征(用于颜色)
self.feat_head = nn.Linear(hidden, hidden)
# 颜色分支(带方向)
self.color_head = nn.Sequential(
nn.Linear(hidden + self.in_dim_dir, hidden // 2),
nn.ReLU(),
nn.Linear(hidden // 2, 3),
nn.Sigmoid(),
)
def forward(self, x, d):
gamma_x = positional_encoding(x, self.pos_L)
gamma_d = positional_encoding(d, self.dir_L)
h = self.backbone(gamma_x)
sigma = self.sigma_head(h).squeeze(-1) # (...,)
feat = self.feat_head(h)
color = self.color_head(torch.cat([feat, gamma_d], dim=-1))
return color, sigma

6.2 训练循环#

import torch.optim as optim
model = NeRF().cuda()
optimizer = optim.Adam(model.parameters(), lr=5e-4)
scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.1 ** (1 / 250000))
for it in range(num_iters):
# 1. 采样一批光线
rays_o, rays_d, gt_colors = sample_rays(dataset)
# 2. 分层采样
t_vals = stratified_sampling(rays_o, rays_d, near, far, N_c=64)
t_vals, _ = importance_sampling(t_vals, weights, N_f=128)
# 3. 查询 MLP
pts = rays_o[..., None, :] + rays_d[..., None, :] * t_vals[..., :, None]
dirs = rays_d[..., None, :].expand_as(pts)
colors, sigmas = model(pts.reshape(-1, 3), dirs.reshape(-1, 3))
colors = colors.reshape(*pts.shape[:-1], 3)
sigmas = sigmas.reshape(*pts.shape[:-1])
# 4. 体渲染
pred_colors, weights = volume_render(sigmas, colors, deltas)
# 5. 损失与优化
loss = F.mse_loss(pred_colors, gt_colors)
optimizer.zero_grad()
loss.backward()
optimizer.step()
scheduler.step()

7. NeRF 的关键改进与变体#

7.1 改进时间线#

年份方法核心贡献
2020NeRF奠基性工作,提出 5D 神经辐射场
2021Mip-NeRF抗锯齿,处理多尺度
2022Instant-NGP哈希编码,5 分钟训练
2022Plenoxels不用 MLP,纯体素网格
2022Mip-NeRF 360处理无界场景
2022NeuS表面重建,高质量几何
20233D Gaussian Splatting实时渲染,显式表示
2023Zip-NeRF工业级质量
20244D-GS / Dynamic 3DGS动态场景

7.2 Instant-NGP:哈希加速#

关键问题:原始 NeRF 的 MLP 查询极其耗时(每条光线数百次前向传播)。

Instant-NGP 的方案:用多分辨率哈希编码替代位置编码。

  • 维护多个分辨率的 3D 网格(哈希表)
  • 每个网格点存一个可学习特征向量
  • 查询时:根据坐标做三线性插值,拼接多分辨率特征
  • 再输入一个小型 MLP(仅 2 层)

效果

  • 训练时间:从 ~12 小时 → 5 分钟
  • 渲染:实时(30 FPS)
  • 显存:仅 ~4 GB

Instant-NGP 是 NeRF 实用化的关键里程碑,使其在工业界真正可用。

7.3 Mip-NeRF:抗锯齿#

问题:训练分辨率与渲染分辨率不同时,NeRF 会出现严重锯齿和模糊。

方案:用**综合多尺度位置编码(IPE, Integrated Positional Encoding)**替代固定阶数的 PE。

  • 考虑每条光线在每个采样段上覆盖的体积(不是点)
  • 用高斯近似的圆锥台体积做积分
  • 天然抗锯齿,支持连续缩放

7.4 Mip-NeRF 360:无界场景#

问题:原始 NeRF 假设相机在场景中心,无法处理 360° 环绕或室外大场景。

方案

  • 使用参数化的无界收缩空间(contracted space)
  • 将远处背景用 MLP 单独处理
  • 提出 interlevel lossdistortion loss,正则化几何

7.5 NeuS:从 NeRF 到表面重建#

动机:NeRF 渲染质量好,但几何是隐式的,难以提取 mesh。

NeuS 的核心:将**符号距离函数(SDF)**与体渲染结合。

  • 用 MLP 预测 SDF s(x)s(\mathbf{x}) 而不是体密度 σ\sigma
  • 通过 SDF 的 Sigmoid 推导 σ\sigma,保证几何一致性
  • 可以直接用 Marching Cubes 提取高质量 mesh

8. NeRF vs 3DGS:核心差异#

8.1 本质对比#

维度NeRF3DGS
表示隐式(MLP)显式(3D 高斯集合)
渲染沿光线采样光栅化 + alpha 合成
训练速度慢(10~24h)快(30~60min)
渲染速度慢(<5 FPS)极快(100+ FPS)
存储MLP 仅 ~5MB场景文件通常 100~500MB
编辑困难天然支持
几何提取困难(需 NeuS)直接(密度场)
动态场景需特殊设计4D-GS 自然扩展

8.2 适用场景#

场景推荐
研究 / 论文基线NeRF(更经典)
工业实时渲染3DGS
几何提取(Mesh)NeuS / 3DGS
神经语义编辑NeRF + Instruct-NeRF2NeRF
物理仿真3DGS(显式几何)
极少训练视角NeRF + 正则化
大规模场景两者都需要分块

9. 进阶话题#

9.1 动态 NeRF / 4D 建模#

  • D-NeRF:把时间作为第 6 维输入
  • Nerfies:形变场 + 规范化空间
  • HyperNeRF:高维拓扑变化(如人脸表情)

9.2 NeRF 编辑#

  • EditNeRF:局部编辑
  • Instruct-NeRF2NeRF:用 2D 扩散模型引导 3D 编辑
  • NeRF-Art:风格化

9.3 NeRF + Diffusion#

  • DreamFusion / Magic3D:用 2D 扩散模型作为先验,从文本生成 3D
  • Zero-1-to-3:单张图像生成新视角

9.4 工业部署#

  • GPU 渲染:原始 NeRF、Instant-NGP、3DGS
  • 移动端:移动 GPU 推理(量化、蒸馏)
  • Web:WebGL / WebGPU 实时查看

10. 关键数学公式汇总#

为方便查阅,下面列出本文涉及的核心公式:

  1. 5D 神经辐射场
Fθ:(x,d)(c,σ)F_\theta: (\mathbf{x}, \mathbf{d}) \rightarrow (\mathbf{c}, \sigma)
  1. 体渲染积分(连续形式)
C(r)=tntfT(t)σ(r(t))c(r(t),d)dtC(\mathbf{r}) = \int_{t_n}^{t_f} T(t) \sigma(\mathbf{r}(t)) \mathbf{c}(\mathbf{r}(t), \mathbf{d}) \, dt
  1. 累积透射率
T(t)=exp(tntσ(r(s))ds)T(t) = \exp\left( -\int_{t_n}^{t} \sigma(\mathbf{r}(s)) \, ds \right)
  1. 离散化体渲染
C^(r)=i=1NTi(1eσiδi)ci\hat{C}(\mathbf{r}) = \sum_{i=1}^{N} T_i (1 - e^{-\sigma_i \delta_i}) \mathbf{c}_i
  1. 位置编码
γ(p)=(sin(20πp),cos(20πp),,sin(2L1πp),cos(2L1πp))\gamma(\mathbf{p}) = \left( \sin(2^0 \pi \mathbf{p}), \cos(2^0 \pi \mathbf{p}), \ldots, \sin(2^{L-1} \pi \mathbf{p}), \cos(2^{L-1} \pi \mathbf{p}) \right)
  1. MSE 损失
L=rRC^(r)Cgt(r)22\mathcal{L} = \sum_{\mathbf{r} \in \mathcal{R}} \left\| \hat{C}(\mathbf{r}) - C_{\text{gt}}(\mathbf{r}) \right\|_2^2

11. 总结与展望#

NeRF 的核心贡献#

  1. 连续表征:用 MLP 表示 5D 连续辐射场,摆脱离散几何的分辨率限制
  2. 体渲染框架:可微的体积积分让端到端训练成为可能
  3. 照片级真实感:在静态场景上达到前所未有的渲染质量
  4. 研究范式:开启了神经隐式 3D 表示的整个研究领域

当前挑战#

  • 训练缓慢:原始 NeRF 需要数小时到一天
  • 渲染效率:每像素需数百次 MLP 查询
  • 相机位姿依赖:需要 COLMAP 等工具预标定
  • 几何提取困难:隐式表示不便于下游几何任务
  • 泛化性:每个场景需独立训练,跨场景泛化能力弱

未来方向#

方向关键工作
加速训练Instant-NGP、Plenoxels、Hash Grid
抗锯齿Mip-NeRF、Mip-NeRF 360
实时渲染3DGS(重要替代方案)
表面重建NeuS、VolSDF
动态 4DD-NeRF、Nerfies、HyperNeRF
文本生成DreamFusion、Magic3D
编辑Instruct-NeRF2NeRF
工业部署模型压缩、移动端、Web 渲染
多模态CLIP-NeRF、LangSplat
大规模Block-NeRF、城市级重建

NeRF 是过去十年计算机视觉最具影响力的工作之一。它的核心思想——“用神经网络隐式表示场景”——已经渗透到 3D 视觉的方方面面。即便 3D Gaussian Splatting 在很多场景取代了它,NeRF 仍然在需要连续隐式表示的科学计算、神经语义编辑、可微仿真等领域持续发光发热。

参考资料#

  1. Mildenhall, B., et al. (2020). “Representing Scenes as Neural Radiance Fields for View Synthesis.” ECCV.
  2. Barron, J. T., et al. (2021). “Mip-NeRF: A Multiscale Representation for Anti-Aliasing Neural Radiance Fields.” ICCV.
  3. Barron, J. T., et al. (2022). “Mip-NeRF 360: Unbounded Anti-Aliased Neural Radiance Fields.” CVPR.
  4. Müller, T., et al. (2022). “Instant Neural Graphics Primitives with a Multiresolution Hash Encoding.” ACM TOG (SIGGRAPH).
  5. Yu, A., et al. (2021). “Plenoxels: Radiance Fields without Neural Networks.” CVPR.
  6. Wang, P., et al. (2021). “NeuS: Learning Neural Implicit Surfaces by Volume Rendering.” NeurIPS.
  7. Park, J. J., et al. (2021). “Nerfies: Deformable Neural Radiance Fields.” ICCV.
  8. Pumarola, A., et al. (2021). “D-NeRF: Neural Radiance Fields for Dynamic Scenes.” CVPR.
  9. Poole, B., et al. (2022). “DreamFusion: Text-to-3D using 2D Diffusion.” arXiv / ICLR 2023.
  10. Haque, A., et al. (2023). “Instruct-NeRF2NeRF: Editing 3D Scenes with Instructions.” ICCV.
  11. Kerbl, B., et al. (2023). “3D Gaussian Splatting for Real-Time Radiance Field Rendering.” ACM TOG (SIGGRAPH).
  12. Martin-Brualla, R., Radwan, N., et al. (2021). “NeRF in the Wild: Neural Radiance Fields for Unconstrained Photo Collections.” CVPR.
  13. Tancik, M., et al. (2022). “Block-NeRF: Scalable Large Scene Neural View Synthesis.” CVPR.
  14. “Nerfstudio: A Modular Framework for Neural Radiance Field Development.” GitHub: nerfstudio-project/nerfstudio.
  15. Kajiya, J. T., & Von Herzen, B. P. (1984). “Ray Tracing Volume Densities.” ACM SIGGRAPH — NeRF 体渲染积分的原始论文。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

深入理解神经辐射场 (NeRF):从体渲染到可微 3D 重建
https://aiattnstudio.link/posts/nerf/
作者
Federico
发布于
2026-07-16
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author

Federico

AI Research Lab

Hello, I'm Federico.

关于实验室 / About
公告

欢迎来到Federico的个人博客

分类
标签
站点统计
57文章
7分类
404标签