This is a term project for the course Data Structures which aims to optimize the storage of voxels in a 3D space, generated by NeRF.
-
run_nerf.py:
- checkpoint的加载改为相对路径模式,更换环境后无需修改
- 在文件末尾的运行mode进行了扩充,对应每个任务
- 对save、render_video 函数调整,以使其在不同模式下使用
- 加入每个模式所用到的新的函数
-
models/hashbase_renderer.py
- 该文件中定义的新renderer起替代原始的renderer功能的作用
- 新renderer包含虚拟渲染时的插入哈希表过程与实际渲染时查询哈希表过程
- 该文件中也定义了一个HashTable类用于哈希表的存储与读写
对基础体素数据的几何重建(可补充--mcube_threshold * 控制sigma的阈值,默认即可)
python run_nerf.py --mode mcube --conf confs/nerf.conf --case test
对比神经渲染与基础体素渲染
python run_nerf.py --mode time_compare --conf confs/nerf.conf --case test
经哈希表改进后的渲染
python run_nerf.py --mode optimized_render --conf confs/nerf.conf --case test
用哈希方法改进后的几何重建(可补充--mcube_threshold * 控制sigma的阈值,默认即可)
python run_nerf.py --mode mcube_hash --conf confs/nerf.conf --case test
所需要的依赖库列在了requirement.txt当中,可以使用pip安装,pip是python自带的依赖库管理与安装工具。在项目目录下打开命令行或者powershell,运行下面的命令即可安装依赖库。
pip install -r requirements.txt
数据集文件为cameras_sphere.npz,包含了渲染时的相机参数。模型文件为nerf_model.pth,包含了训练好的nerf模型。接下来需要新建dataset文件夹,在dataset下再新建test文件夹,把数据集文件放进去即可。 运行代码指令为
python run_nerf.py --mode test --conf confs/nerf.conf --case test
在cpu模式下,等待1-10分钟后,将在exp/test/render
文件夹下生成渲染图片0.jpg
在test模式下,程序会调用CheatNeRF
类,这个类会直接调用NeRF来渲染,所以渲染速度会非常慢。
测试渲染通过后,我们需要实现本作业的基础目标。基础目标渲染代码的运行方式为:
python run_nerf.py --mode render --conf confs/nerf.conf --case test
整个渲染分成两个过程,一个是将nerf的属性保存到数据结构中的save过程,一个是给定点的位置,查询nerf属性的查询过程。
save过程的主体在run_nerf.py
当中,它会密集地在[-0.125, 0.75, -0.125]到[0.125, 1.0, 0.125]这个范围内采集RSxRSxRS
个点,并询问神经网络每个点的属性。询问后会调用models/my_nerf.py
中MyNeRF
的save函数,你需要实现save函数,将这些点的属性保存到你的数据结构中。初始时RS
为64,此时由于采样分辨率过低,按照这样渲染出来的图像会有很多噪声,不过这样运行速度会很快,方便调试。等跑通后可以将RS
改为128,就可以渲染一个正常的结果。
你需要实现models/my_nerf.py
中MyNeRF的query函数,它的输入pts_xyz为Nx3的浮点类型数组代表每个点的位置,你需要输出一个Nx1的数组sigma代表每个点的密度,Nx3的数组color代表每个点的颜色。注意这里点的位置是实数,所以很大概率和save过程采的点不一样,可以按照高级快速索引中给的代码,求取整后的结果。当然也可以找最近点。
渲染参数当中一个比较重要的参数是resolution_level
,它可以填1,2,4
,填1时会渲染512x512分辨率的图像,填2时是256x256,填4时是128x128。初始调试的时候尽量填4,渲染更低分辨率的图像速度会快很多。等没有bug时再调成1或者2来提高渲染质量。另外如果没有实现进阶目标,因为我们数据结构的数组大小只有128x128x128,所以填2或者1可能也没有实质作用。
如果每次主程序的save过程都很耗时,也可以通过torch.save来直接保存数据结构。保存数据结构到硬盘以后,可以跳过主程序的save过程,从硬盘读取来做渲染。
# save to the disk
checkpoint = {
"volume_sigma": self.volume_sigma,
"volume_color": self.volume_color
}
torch.save(checkpoint, "temp.pth")
# load from the disk
checkpoint = torch.load("temp.pth")
self.volume_sigma = checkpoint["volume_sigma"]
self.volume_color = checkpoint["volume_color"]