NeRF 源码解读(一)

前言

NeRF 是三维视觉中新视图合成任务的启示性工作,最近领域内出现了许多基于 NeRF 的变种工作。本文以pytorch 版 NeRF 作为基础对 NeRF 的代码进行分析。
主要从以下方面开展:

  1. 数据的加载
  2. 光线的生成
  3. NeRF 网络架构
  4. 渲染过程

一、数据的加载

本文以加载合成数据集中 lego 图像为例。
首先我们观察 ./data/nerf_synthetic/lego 文件夹下的树结构:

train、test、val 三个文件夹下包含了训练要用到的 .png 图像,每个文件夹下包含 100 个文件。.json 文件包含了相机的 camera2word 转置矩阵,下图展示了部分文件中的内容。关于此转置矩阵不再展开叙述,具体知识可查看 SLAM 14 讲。了解以上基本信息后解析数据加载的代码。

frame 的值是一个列表,其中列表中的值是字典

def train():# 设置参数parser = config_parser()args = parser.parse_args()...elif args.dataset_type == 'blender':images, poses, render_poses, hwf, i_split = load_blender_data(args.datadir, args.half_res, args.testskip)print('Loaded blender', images.shape, render_poses.shape, hwf, args.datadir)i_train, i_val, i_test = i_split# 设定边界框的远近边界near = 2.far = 6.# 将 RGBA 转换成 RGB 图像if args.white_bkgd:# 如果使用白色背景images = images[...,:3]*images[...,-1:] + (1.-images[...,-1:])else:images = images[...,:3]

我们通过 load_blender_data() 函数得到了指定文件夹下的所有图像、pose、测试渲染的pose、宽高焦距以及分割数组。下面对数据加载函数进行分析。

def load_blender_data(basedir, half_res=False, testskip=1):""":param basedir: 数据文件夹路径:param half_res: 是否对图像进行半裁剪:param testskip: 挑选测试数据集的跳跃步长:return: """splits = ['train', 'val', 'test']metas = {}for s in splits:# 分别加载三个 .json 文件,保存到字典中with open(os.path.join(basedir, 'transforms_{}.json'.format(s)), 'r') as fp:metas[s] = json.load(fp)all_imgs = []all_poses = []counts = [0]for s in splits:meta = metas[s]  # 加载 .json 文件中的内容imgs = []poses = []# 如果是 train 文件夹,连续读取图像数据if s=='train' or testskip==0:skip = 1else:skip = testskipfor frame in meta['frames'][::skip]:# 以指定步长读取列表中的字典fname = os.path.join(basedir, frame['file_path'] + '.png')imgs.append(imageio.imread(fname))  # 将读取到的图像文件添加到图像列表中poses.append(np.array(frame['transform_matrix']))  # 读取转置矩阵imgs = (np.array(imgs) / 255.).astype(np.float32) # 此时 图像数组是一个 [n, H, W, 4] 的数组poses = np.array(poses).astype(np.float32)  # [n, 4, 4]counts.append(counts[-1] + imgs.shape[0])  # 用于标定到train、test、valall_imgs.append(imgs)  # 包含了 train、test、val 的图像的列表all_poses.append(poses)i_split = [np.arange(counts[i], counts[i+1]) for i in range(3)]imgs = np.concatenate(all_imgs, 0)  # 把列表聚合称为一个数组 [N, H, W, 4]poses = np.concatenate(all_poses, 0)H, W = imgs[0].shape[:2]camera_angle_x = float(meta['camera_angle_x'])focal = .5 * W / np.tan(.5 * camera_angle_x)  # 计算焦距# 制作用于测试训练效果的 渲染poserender_poses = torch.stack([pose_spherical(angle, -30.0, 4.0) for angle in np.linspace(-180,180,40+1)[:-1]], 0)# 为了节省内存开销可以选择只加载一半的数据,这里不再展开解释if half_res:H = H//2W = W//2focal = focal/2.imgs_half_res = np.zeros((imgs.shape[0], H, W, 4))for i, img in enumerate(imgs):imgs_half_res[i] = cv2.resize(img, (W, H), interpolation=cv2.INTER_AREA)imgs = imgs_half_res# imgs = tf.image.resize_area(imgs, [400, 400]).numpy()return imgs, poses, render_poses, [H, W, focal], i_split

通过对以上代码的分析,我们可以得到以下结果:

imgs : 根据 .json 文件加载到的所有图像数据。(N,H,W,4)N 代表用于 train、test、val 的总数量
poses : 转置矩阵。(N,4,4)
render_poses : 用于测试的 pose 。(40,4,4)
i_split : [[0:train], [train:val], [val:test]]

完成数据加载以后,就可以根据 image 数据模拟生成光线。具体代码解析见下一节:
NeRF源码分析解读(二)

NeRF 源码分析解读(一)相关推荐

  1. loam_continuous源码分析解读

    loam_continuous源码逐行分析--scanRegistration 写在前面 scanRegistration imuHandler laserCloudHandler 总结 写在前面 最 ...

  2. ATS插件channel_stats源码分析解读

    简介 channel_stats插件能对每个channel收集运行时统计信息(速率,请求数,更多选项将在未来添加),这些统计信息通过http json方式输出,这些 接口代码取自stats_over_ ...

  3. 基于后端开发Redisson实现分布式锁源码分析解读

    一.分布式锁的概念和使用场景 分布式锁是控制分布式系统之间同步访问共享资源的一种方式. 在分布式系统中,常常需要协调他们的动作.如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问 ...

  4. Spark源码解读之Shuffle原理剖析与源码分析

    在前面几篇文章中,介绍了Spark的启动流程Spark内核架构流程深度剖析,Spark源码分析之DAGScheduler详解,Spark源码解读之Executor以及Task工作原理剖析,Spark源 ...

  5. java io源码解读_Java IO源码分析(五)——CharArrayReader 和 CharArrayWriter

    简介 CharArrayReader 是字符数组的输入流,它和我们之前讲的ByteArrayInputStream十分类似,顾名思义,区别在于一个用于字符数组,一个用于字节数组,在Java中字符是16 ...

  6. 【源码解读】Screencap源码分析-基础篇

    本文期望达到的目的: 了解screencap使用 了解screencap实现基础原理 为后续screencap源码修改和其他应用做准备 源码位置: android4.0之后内置了截图工具screenc ...

  7. Laravel核心解读--Cookie源码分析

    Laravel Cookie源码分析 使用Cookie的方法 为了安全起见,Laravel 框架创建的所有 Cookie 都经过加密并使用一个认证码进行签名,这意味着如果客户端修改了它们则需要对其进行 ...

  8. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

  9. ConcurrentHashMap实现原理及源码分析

    ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对HashMap的实现原理还不甚了解,可参考我的另一篇文章HashMap实现原理及源码分析),Con ...

最新文章

  1. com.alibaba.druid.sql.parser.ParserException: ERRO
  2. My Account dependency /UI5/CL_UI5_APP_INDEX_LREP~UI5_INFO_FETCH_FROM_DB strange manifest.json
  3. windows 检查cuda安装_Windows云主机GPU驱动-CUDA安装使用
  4. 无规则弹窗自动点击插件_vscode 插件会了吧,英语不好的赶紧下载 自动分析源码中的陌生单词、点击朗读单词...
  5. STM32串口通信中使用printf发送数据配置方法 开发环境 Keil
  6. vc中运行外部程序的方法
  7. 房费制——报表(1)
  8. 离散时间信号常见函数的实现(matlab)
  9. DotNetNuke 04.05.05 安装
  10. xp安全模式下如何修复计算机,xp安全模式下怎么解决蓝屏_xp开机进入安全模式修复蓝屏教程...
  11. Excel批量对比工具分享
  12. CTF密码学之Base64,Base32,Base16
  13. java id 锁_java 多线程synchronized同步锁锁住相同用户Id
  14. springboot前后端分离图片上传接口
  15. 处理 unity崩溃日志
  16. IOB Inside-outside-beginning (tagging)
  17. 卫星过顶计算matlab,基于SGP4模型的卫星轨道计算.docx
  18. PID中各个参数意义
  19. 给初级beatles热爱者提供的歌曲MP3下载
  20. vue--单页面应用和多页面应用

热门文章

  1. 在 Windows Server 2003 企业服务器中如何配置 IPv6 协议
  2. Apache Druid 总结
  3. 2004-10-30 周六
  4. Java通过mongo-java-driver-3.0+查询mongodb数据库
  5. FME中的栅格数据操作之一——转换器小结
  6. 浏览器内核和Standards模式与Quirks模式
  7. c++学习:多线程;顺序容器;智能指针
  8. 010序列检测电路设计
  9. 基于FPGA的遥控数字时钟设计
  10. 评估EtherCAT从站节点解决方案