NeRF论文复现1 --- 代码运行和数据集分析

NeRF是近年来神经网络发展的一大丰碑,几年前第一遍看这篇论文的时候几乎马上就爱上了这个研究(这个体验是很少的,大部分论文看一遍要么盲目地觉得我上我也行,要么直接不知道它想干嘛)。不过由于走学术弯路和工作重心不在这等等原因,一直也没仔细去看这一系列的工作。直到最近开始看可微渲染相关的内容,才觉得这块得好好补一补。于是从旧笔记堆里又把这篇原始论文翻出来开始研究。

这篇博客就是之前写的官方代码运行的记录,主要介绍如何在Windows以及Linux上快速运行起Nerf的代码(Pytorch版本,注意官方实现用的是Tensorflow,但这个Pytorch版本也被非常多人作为参考标准,如果要保证100%复现,可能得去看Tensorflow的版本),以及数据集的简单分析。

代码运行

Windows+Linux

大部分操作是一样的,因此没有分开写,差别的地方已经注明了。

源码拷贝

bash 复制代码
git clone https://github.com/yenchenlin/nerf-pytorch.git
cd nerf-pytorch

虚拟环境配置

注意,这份代码是六七年前开源的,之后没改过。

Ubuntu

bash 复制代码
conda create -n nerf_pytorch python=3.9
conda activate nerf_pytorch
pip install -r requirements.txt

一般上面那些就行,但因为年代久远的问题,可能会出现兼容性错误。比如我用的是RTX4090,用requiremnts里面的pytorch版本就会出问题。因此使用支持CUDA12.1的2.5.1。如果不想搞两遍也可以删掉requirements.txt的相关内容然后自己用最后一句话装一下就好,这样的话numpy也可以用2.0的版本。

bash 复制代码
# 老显卡一般只需要这一步就行
# 降级 NumPy 到 1.x 版本。
pip install "numpy<2"
# 新显卡还需要这两步操作。
# 卸载当前 PyTorch
pip uninstall torch torchvision torchaudio
# 安装支持 CUDA 12.1 的 PyTorch(RTX 4090 需要)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121

windows

bash 复制代码
conda create -n nerf_pytorch python=3.9
conda activate nerf_pytorch
conda install pytorch torchvision torchaudio pytorch-cuda=11.8 -c pytorch -c nvidia
pip install imageio
pip install imageio-ffmpeg
pip install matplotlib
pip install configargparse
pip install tensorboard
pip install tqdm
pip install opencv-python

运行示例

下载数据

安装git和wget(Linux下不需要这一步,如果没有git命令行安装一下即可)

Windows下运行下一步的sh文件需要git,没有的话需要先安装:

https://git-scm.com

windows上没有wget命令,因此也需要配置上去,方法是:

1、下载wget二进制安装包,地址:https://eternallybored.org/misc/wget/

2、解压安装包,将wget.exe 拷贝到C:\xx\Git\mingw64\bin中(这里的地址和git的安装位置有关)

数据下载

在Windows下,需要在sh文件所在的位置后右键选择"Git Bash Here",然后在控制台上输入(Linux上直接终端cd到对应位置输入即可):

bash 复制代码
bash download_example_data.sh

下载完成的数据在data文件夹中。

训练神经网络

完成上述操作后只需运行如下命令即可进行训练:

bash 复制代码
python run_nerf.py --config configs/lego.txt

训练完后会在logs/lego_test/lego_test_spiral_100000_rgb.mp4路径下生成mp4文件,这也是imageio-ffmpeg这个库的作用。(整个过程需要的时间比较感人,RTX 4090:3h左右,A4000:9h左右)

如果希望保留控制台的训练过程,也可以使用下面的命令:

bash 复制代码
python run_nerf.py --config configs/lego.txt 2>&1 | tee output.log

数据集分析

下载下来的数据集里面有两个文件夹,分别是nerf_llff_data和nerf_synthetic。文件夹中分别只有一个场景,后者是由blender渲染生成的乐高积木推土机,也是论文出现频次最多的一个场景:

nerf一次只能训练一个场景的内容,因此看懂单个场景里面有什么也就知道nerf要求的数据的样子了。

单场景数据结构

单个场景的数据结构如下:

  • lego

    • test
      • 不同视角的深度图、渲染图
    • train
      • 不同视角的渲染图
    • val
      • 不同视角的渲染图
        transforms_test.json
        transforms_train.json

    transforms_val.json

每个json文件中分别存储相机的水平视场角以及多帧图像中的每一帧图像存放的路径和世界坐标系。虽然相机的内参没有直接在json文件中给出,但Nerf使用的是理想针孔相机模型,可通过水平视场角计算得到。

在run_nerf.py文件的images, poses, render_poses, hwf, i_split = load_blender_data(args.datadir, args.half_res, args.testskip)这个语句后面加入如下代码,可以将各个图像的拍摄相机视锥进行可视化:

python 复制代码
 # 可以在这里使用Open3D将各个相机可视化出来
# poses里面存放着相机的外参,hwf存放着图像的高宽和焦距
import open3d as o3d
# 遍历所有的相机位姿
camera_frames = []
for i in range(poses.shape[0]):
    # Blender transform_matrix 是相机到世界(c2w, OpenGL: +X 右, +Y 上, -Z 朝前)
    # Open3D 的 create_camera_visualization 期望 extrinsic 为世界到相机(w2c, OpenCV: +Z 朝前, +Y 向下)
    # 因此需要先取逆得到 w2c_opengl,再做 OpenGL -> OpenCV 轴变换 (flip y,z)
    w2c_opengl = np.linalg.inv(poses[i])
    flip_yz = np.eye(4)
    flip_yz[1, 1] = -1
    flip_yz[2, 2] = -1
    extrinsic = flip_yz @ w2c_opengl
    # 构建相机内参
    intrinsic = np.array([[hwf[2], 0, hwf[1]/2],
                          [0, hwf[2], hwf[0]/2],
                          [0, 0, 1]
                         ])
    cameraLines = o3d.geometry.LineSet.create_camera_visualization(
        view_width_px=int(hwf[1]), view_height_px=int(hwf[0]),
        intrinsic=intrinsic, extrinsic=extrinsic, scale=0.5)# 这里scale是相机图标的大小,设置为0.5视觉效果会比较好

    if i in i_split[0]: # 训练集为蓝色
        cameraLines.paint_uniform_color((0, 0, 1))  # Blue
    elif i in i_split[1]: # 验证集为黄色
        cameraLines.paint_uniform_color((1, 1, 0))  # Yellow
    else: # 测试集为红色
        cameraLines.paint_uniform_color((1, 0, 0))  # Red
    camera_frames.append(cameraLines)

vizualizer = o3d.visualization.Visualizer()
vizualizer.create_window(window_name='Camera Pose', width=800, height=600)
for camera in camera_frames:
    vizualizer.add_geometry(camera)
vizualizer.run()
vizualizer.destroy_window()

其中训练数据为蓝色,验证数据为黄色而测试数据为红色。

参考文章

https://github.com/yenchenlin/nerf-pytorch

相关推荐
charlee446 天前
最小二乘问题详解:目录
最小二乘法·三维重建·sfm·ceres solver·bundle adjustment
大势智慧12 天前
智影R200免像控空地融合建模解决方案
高精度·解决方案·slam·三维重建·三维扫描·手持slam·空地融合
AGV算法笔记12 天前
CVPR 2024顶级SLAM论文精读:SplaTAM如何用3D高斯实现稠密RGB-D SLAM?
深度学习·3d·机器人视觉·slam·三维重建
AGV算法笔记14 天前
CVPR 2025顶级SLAM论文精读:MASt3R-SLAM如何用单目相机实现实时稠密三维重建?
深度学习·数码相机·机器人视觉·slam·三维重建·agv
_寒潭雁影23 天前
NeRF论文复现2 --- 原理及源码解析
神经网络·三维重建·nerf·神经辐射场·三维表达
GISBox25 天前
三大维度焕新!GISBox2.2.0新增三维重建模块与性能优化
gis·三维重建·gisbox·rvt·服务数据缓存·ktx2·win7系统
搬砖者(视觉算法工程师)1 个月前
3D模型生成之有向距离场(SDF)和光线行进(Ray Marching)
三维重建
搬砖者(视觉算法工程师)1 个月前
对占用网络(Occupancy Networks)的简单介绍
三维重建