本项目实现了从静态到动态场景的完整 NeRF 技术链,包括位置编码、多视图重建、Instant-NGP 加速、D-NeRF 动态建模,以及创新的 Dual-Hash 动态 NeRF 架构。
项目完整报告: Final Report
测试环境:代码已在 Ubuntu 22.04 上使用 NVIDIA RTX 4060 Laptop GPU (8GB) 进行测试。实验使用 PyTorch 2.1.2 和 CUDA 12.1,其他版本可能也兼容。
主要性能:
- Part 2 (NeRF): Lego 数据集 2达到 24.75 dB PSNR (20k steps)
- Part 2 (Instant-NeRF): Lego 数据集 5 分钟训练达到 26+ dB,渲染速度 10+ FPS
- Part 3 (D-NeRF Instant): Standup 数据集达到 28 dB (20k steps, ~2h)
- Part 4 (Dual-Hash): Standup 数据集达到 30.58 dB (5k steps, ~9 分钟)
北大网盘 存放了项目的数据集和预训练模型,结果。
本项目已在以下环境测试通过:
- Python 3.13
- PyTorch 2.1.2
- CUDA 12.1
- GPU: 8GB 显存 (RTX 4060 laptop)
- 克隆代码并创建虚拟环境
# 1. 克隆代码
git clone https://github.com/CV-Project2025/Project-NeRF
cd Project-NeRF
# 2. 创建并激活环境
python3 -m venv .venv
source .venv/bin/activate
# 3. 安装依赖
pip install -r requirements.txt- TinyCUDA-NN 依赖安装
鉴于本项目主要代码运行都要依靠 TinyCUDA-NN ,请从 网盘 下载 install_ngp.sh 放置到项目文件夹运行一下,以确保所需的 TinyCUDA-NN 和相关组件正确安装。
- 配置自定义
将 configs/part{num}.yaml.example 复制一份并重命名为 configs/part{num}.yaml,并根据需要修改配置文件中的参数。
1. 数据准备
从 网盘 获取 fox.jpg,放置到 data/ 目录下。
2. 训练
python3 run.py --image data/fox.jpg --config configs/part1.yaml训练约 5-10 分钟,PSNR 可达 35+ dB。训练日志实时保存到 TensorBoard。
3. 测试
Part 1 训练过程中会自动进行拟合效果渲染。如果需要手动使用 checkpoint,请先从 网盘 下载模型 model_final.pth,然后运行:
python3 run.py --image data/fox.jpg --config configs/part1.yaml --checkpoint <path_to_model> --eval_only4. 输出说明
- 训练日志与 TensorBoard 文件保存在
output/runs/。 - 每个
save_every步数会保存当前拟合的图片到output/runs/<run_id>/steps/。 - 最终结果保存为
final.png。 - PSNR 值越高(如 > 35dB)代表拟合精度越高。
1. 数据准备
建议下载 NeRF Synthetic 数据集,放置在 data/下,可以从 网盘/part2/data 获取。
2. 训练
python3 run.py --data_dir data/nerf_synthetic/lego --config configs/part2.yaml训练 20k steps 约需 2 小时 (batch 4096)。测试集 PSNR 约 24.75 dB。训练日志和 checkpoints 保存在 output/part2/。
3. 测试
请先从 网盘/part2/result 下载预训练模型并放置到 output/part2/checkpoints/ 目录下,然后运行:
python3 run.py --data_dir data/nerf_synthetic/lego --config configs/part2.yaml \
--checkpoint output/part2/checkpoints/model_step_020000.pth --eval_only4. 输出说明
- 训练输出默认保存在 output/part2/ 目录
- 测试集渲染结果位于 output/part2/renders/
- 若数据集中没有 transforms_test.json,程序会自动使用 val 集合进行评估
- 若显存不足,可在运行时指定更小的渲染块大小,例如 --render_chunk 4096
1. 数据准备
数据同标准 NeRF,注意要保证相关 依赖 已安装。
2. 训练
python3 run.py --data_dir data/nerf_synthetic/lego --config configs/part2_instant.yaml训练速度极快:1 分钟内可见细节,5 分钟达到 26+ dB PSNR。渲染速度 10+ FPS。训练日志保存在 output/part2_instant/lego/。
3. 测试
请先从 网盘/data/Instant-NeRF result 下载预训练模型并放置到 output/part2_instant/lego/ 目录下,然后运行:
# --render_n 参数:-1表示生成视频,正数表示随机渲染指定数量的视角
python3 run.py --data_dir data/nerf_synthetic/lego --config configs/part2_instant.yaml \
--checkpoint output/part2_instant/lego/best_model.pth --eval_only --render_n -14. 输出说明
- 结果保存在
output/part2_instant/。 - 使用 TensorBoard 监控损失下降与 PSNR 实时变化。
- 训练和渲染速度较快,可根据需要调整 配置 中
batch_size和chunk参数以适配显存。
Part 3 提供三种架构:
- Part 3 标准版 (
part3.yaml):Fourier MLP 变形场 + Fourier MLP 规范场 - Part 3 DTC (
part3_dtc.yaml):Direct Time Conditioning,无变形场,直接拼接时间编码 - Part 3 Instant (
part3_instant.yaml):Fourier MLP 变形场 + Hash 规范场(推荐)
1. 数据准备
使用 D-NeRF 数据集,可从 网盘/part3/data 获取并在 data/ 下解压重命名为d-nerf。
2. 训练
# 推荐:Instant 版本(速度最快,效果好)
python3 run.py --data_dir data/d-nerf/standup --config configs/part3_instant.yaml训练 20k steps 约 2 小时,测试集 PSNR 约 28 dB。支持多种正则化策略和动态占据网格加速。
# 标准版本(收敛慢,需要更长训练时间)
python3 run.py --data_dir data/d-nerf/standup --config configs/part3.yaml训练 40k steps 约 13 小时,测试集 PSNR 约 25 dB。
# Direct Time Conditioning(实验性架构,适合动作简单的场景,几乎无法收敛)
python3 run.py --data_dir data/d-nerf/standup --config configs/part3_dtc.yaml
训练 50k steps 约 16 小时,测试集 PSNR 约 23 dB。无变形场解耦,收敛困难。
3. 测试
请先从 网盘/part3/result 下载预训练模型并放置到 output/part3/standup/ 目录下,然后运行:
# --render_n 参数:-1表示生成视频,正数表示随机渲染指定数量的视角
python3 run.py --data_dir data/d-nerf/standup --config configs/part3_instant.yaml \
--checkpoint output/part3/standup/best_model.pth --eval_only --render_n -14. 输出说明
- 训练结果保存在
output/part3/<dataset_name>(标准/Instant)或output/part3_direct/<dataset_name>(DTC)。 - 生成的视频会保存为
<dataset_name>_24fps.mp4。 - 支持环绕渲染(相机旋转 + 时间变化)。
实验目标:通过三网格时间锚点架构实现高质量动态场景重建。
核心创新:
- Tri-Grid 时间锚点:在 t=0, 0.5, 1 三个时刻使用独立 HashGrid,通过三角形加权插值实现 C1 连续
- TV-Displacement Loss:对位移网格施加全变分正则化,消除物体边缘闪烁
- Static Anchor Loss:强制 t=0 时零位移,确保规范空间有明确定义
1. 数据准备
使用与 Part 3 相同的 D-NeRF 数据集。
2. 训练
python3 run.py --data_dir data/d-nerf/standup --config configs/part4.yaml训练 5000 steps 仅需约 9 分钟,测试集 PSNR 达到 30.58 dB (训练集 32.41 dB,验证集 29.56 dB)。相比 Part 3 Instant 版本提速 10 倍以上,质量更优且无高频震荡。训练日志和最佳模型保存在 output/part4/standup/。
3. 测试
请先从 网盘/part4/result 下载预训练模型并放置到 output/part4/standup/ 目录下,然后运行:
# 只测试 PSNR
python3 run.py --data_dir data/d-nerf/standup --config configs/part4.yaml \
--checkpoint output/part4/standup/best_model.pth --eval_only
# 生成环绕视频(300 帧)
python3 run.py --data_dir data/d-nerf/standup --config configs/part4.yaml \
--checkpoint output/part4/standup/best_model.pth --eval_only --render_n -14. 输出说明
- 训练结果保存在
output/part4/<dataset_name>。 - 使用
--eval_only模式会跳过视频渲染,仅输出测试集 PSNR。 - 视频文件命名为
<dataset_name>_part4_24fps.mp4。
Project-NeRF/
├── configs/ # 实验配置文件
│ ├── part1.yaml.example # 2D 拟合配置模板
│ ├── part2.yaml.example # 标准 NeRF 配置模板
│ ├── part2_instant.yaml.example # Instant-NGP 配置模板
│ ├── part3.yaml.example # Dynamic NeRF 标准版
│ ├── part3_instant.yaml.example # Dynamic NeRF Instant 版(推荐)
│ ├── part3_dtc.yaml.example # Dynamic NeRF Direct Time Conditioning
│ └── part4.yaml.example # Dual-Hash Dynamic NeRF
├── data/ # 数据存放目录
│ ├── d-nerf/ # D-NeRF 动态场景数据集 (Part 3 & 4)
│ ├── nerf_synthetic/ # NeRF Synthetic 静态场景数据集 (Part 2)
│ └── part1/ # Part 1 2D 拟合数据 (如 fox.jpg)
├── output/ # 实验输出 (日志, checkpionts, 渲染图)
├── src/ # 核心代码
│ ├── __init__.py
│ ├── abstract.py # 抽象基类定义
│ ├── core.py # 神经场核心逻辑 (组装embeddings, decoders)
│ ├── dataset.py # 数据加载
│ ├── decoders.py # 网络结构
│ ├── embeddings.py # 编码器
│ ├── renderer.py # 渲染器
│ └── utils.py # 通用工具
├── run.py # 统一运行入口
├── requirements.txt
└── README.md
实验目标:让神经网络学习并记住一张二维图像的像素分布
核心原理:
- 频谱偏差 (Spectral Bias):标准 MLP 倾向于学习低频信号,导致直接输入坐标无法拟合高频细节(图像模糊)。
- 位置编码 (Positional Encoding):通过傅里叶特征映射将低维坐标映射到高维频率空间,使网络能捕获高频细节。 $$ \gamma(p) = (\sin(2^0\pi p), \cos(2^0\pi p), ..., \sin(2^{L-1}\pi p), \cos(2^{L-1}\pi p)) $$
架构设计:
-
输入:像素坐标
$(x, y)$ ,归一化到$[-1, 1]$ 。 -
编码层:
FourierRepresentation,将坐标扩展为$2+4L$ 维向量。 -
网络:
StandardMLP,全连接层 + ReLU 激活。 - 输出:RGB 颜色值。
实验目标:通过稀疏的多视角 2D 图像,重建 3D 场景的几何与外观。
核心原理:
-
体渲染 (Volume Rendering):物理模型,通过沿着光线积分密度 (
$\sigma$ ) 和颜色 ($c$ ) 来合成图像颜色。 $$ C(r) = \int_{t_n}^{t_f} T(t) \sigma(r(t)) c(r(t), d) dt $$ - 光线投射 (Ray Marching):在每条光线上采样点,输入网络查询密度和颜色,最后累加。
架构设计:
-
输入:空间坐标
$(x, y, z)$ 和 观察方向$(\theta, \phi)$ 。 - 编码层:对位置和方向分别进行位置编码。
-
网络:
NeRFDecoder(Standard MLP)。- 输入位置
$\to$ 输出密度$\sigma$ 和特征向量。 - 特征向量 + 观察方向
$\to$ 输出颜色 RGB。
- 输入位置
- 输出:该点的密度和视点相关的颜色。
实验目标:加速 NeRF 训练与渲染过程。
核心原理:
-
多分辨率哈希编码:
- 使用可学习的哈希表存储特征,替代固定的三角函数编码。
- 使用哈希冲突(Hash Collision)来换取
$O(1)$ 的查询速度和巨大的参数空间。 - 能够在极小的计算开销下捕捉极其精细的几何细节。
-
Density Grid:
- 维护一个粗糙的体素网格,标记空区域。
- 光线投射时跳过空区域,大幅减少无效采样,提升效率。
架构设计:
-
编码层:
HashRepresentation(TinyCUDA-NN 实现)。 -
网络:
InstantNeRFDecoder(Tiny MLP),通常只有 1-2 层隐含层,计算极快。 -
流程:Hash Encodings
$\to$ Tiny MLP$\to$ RGB/$\sigma$。
实验目标:重建动态变化的 3D 场景(时间
核心原理:
-
变形场 (Deformation Field):
- 假设物体仅发生几何形变,将动态空间的坐标
$(x, t)$ 映射到规范空间 (Canonical Space) 的坐标$x_c$ 。 - $$ x_c = x + \Delta x(x, t) $$
-
$\Delta x$ 由一个变形网络预测。
- 假设物体仅发生几何形变,将动态空间的坐标
-
规范场 (Canonical NeRF):
- 在规范空间中训练一个静态的 NeRF 模型。
- 为了处理随时间变化的光影(非几何变化),规范网络的输入通常也会融合时间特征。
架构设计(标准版 & Instant 版):
-
变形网络 (
DeformNet):- 输入:位置
$x$ (Fourier 编码) + 时间$t$ (Fourier 编码)。 - 输出:位移向量
$\Delta x$ 。
- 输入:位置
-
规范网络 (
CanonicalNet):- 输入:规范位置
$x_c = x + \Delta x$ (Fourier/Hash 编码) + 时间$t$ + 观察方向$d$ 。 - 输出:$RGB, \sigma$。
- 输入:规范位置
架构设计(Direct Time Conditioning):
-
无变形场:直接将原始坐标
$x$ 、时间$t$ 、方向$d$ 的编码拼接输入 MLP -
单一解码器:
- 输入:$[\text{embed}(x), \text{embed}(t), \text{embed}(d)]$
- 输出:$RGB, \sigma$
- 优势:架构简单,无需学习复杂的变形映射
- 局限:难以处理大幅度几何变形,适合简单周期性动作(如关节旋转)
技术创新:
-
网络架构增强:
- 时变规范特征:将时间编码特征直接拼接到规范空间特征中,增强模型对随时间变化的光影(如移动高光、阴影)的建模能力。
- 混合架构:结合 Instant-NGP HashGrid(规范场)与 MLP(变形场),在保持动态效果的同时大幅提升训练速度。
-
数据增强:
-
坐标噪声注入:在训练时对变形网络的输入
$(x, t)$ 添加微小噪声$(x \pm \epsilon)$ ,强制模型在邻域内输出相似位移,显著增强变形场的空间平滑性。 - 随机背景:训练时随机切换背景颜色(黑/白/噪点),防止模型利用背景过拟合,提高抠图质量。
- 体积守恒约束:对随机采样时刻的变形场施加约束,要求物体在不同时刻保持全局体积守恒,防止物体凭空膨胀或收缩。
-
坐标噪声注入:在训练时对变形网络的输入
-
正则化:
- 变形 L2 正则:防止形变过大。
- TV Loss:平滑 HashGrid 特征。
- 时间平滑:保证动作连贯。
实验目标:通过全哈希架构实现动态场景的高效高质量重建。
核心创新:
-
Tri-Grid 时间锚点 (Tri-Grid Temporal Anchoring):
- 使用三个独立的 HashGrid 分别记录
$t=0, 0.5, 1$ 时刻的位移场 - 通过三角形加权插值(而非分段线性)实现 C1 连续的时间插值
- 权重公式:$w_i = \max(0, 1 - |t - t_i| / 0.5)$,归一化后加权平均
- 解决问题:消除视频中 t=1/6, 1/2, 5/6 附近的卡顿现象
- 使用三个独立的 HashGrid 分别记录
-
Dual-Hash 协同架构:
-
位移场:三个 HashGrid(
deform_grid_start/mid/end)+ 轻量 MLP 解码器 - 规范场:单个 HashGrid + Instant-NGP 解码器
- 优势:位移场和规范场都使用哈希表,训练速度快,表达能力强
-
位移场:三个 HashGrid(
-
TV-Displacement Loss:
- 对位移哈希网格施加全变分正则化:$\mathcal{L}{TV} = \sum |p_i - p{i+1}|$
- 效果:强制相邻哈希条目的位移向量相似,消除白色边缘闪烁和哈希碰撞噪点
-
Static Anchor Loss:
- 强制
$t=0$ 时刻deform_grid_start输出零位移 - 保证规范空间有明确定义(第一帧 = 规范姿态)
- 消除底座抖动、避免规范空间漂移
- 强制
架构设计:
-
时间编码 → 时间调制网络:
- 输入:时间
$t$ 的 Fourier 编码 - 输出:时间调制向量(用于控制位移强度)
- 设计:2 层轻量 MLP + Sigmoid 门控
- 输入:时间
-
三网格位移解码:
- 输入:空间坐标
$x$ → 三个 HashGrid 查询 → 插值融合 + 时间调制 - 输出:位移向量
$\Delta x$
- 输入:空间坐标
-
规范场渲染:
- 输入:规范位置
$x_c = x + \Delta x$ → HashGrid 编码 + 时间特征 + 方向 - 输出:$RGB, \sigma$
- 输入:规范位置
正则化策略:
| 正则项 | 权重 | 作用 |
|---|---|---|
| TV-Displacement | 0.0001 | 消除位移网格的高频噪声和边缘闪烁 |
| TV-Canonical | 0.000001 | 平滑规范空间哈希特征 |
| Deformation L2 | 0.0001 | 限制位移幅度,防止几何扭曲 |
| Temporal Smooth | 0.0001 | 强制相邻时刻位移连续 |
| Static Anchor | 0.001 | t=0 时零位移约束 |
性能对比:
- 训练速度:比 Part 3 标准版快 5-10 倍
- 渲染质量:与 Part 3 Instant 相当或更优(取决于正则化调优)
- 视频流畅度:三角形插值显著改善时间连续性