【三维重建】【深度学习】NeuS代码Pytorch实现--测试阶段代码解析(下)

【三维重建】【深度学习】NeuS代码Pytorch实现–测试阶段代码解析(下)

论文提出了一种新颖的神经表面重建方法,称为NeuS,用于从2D图像输入以高保真度重建对象和场景。在NeuS中建议将曲面表示为有符号距离函数(SDF)的零级集,并开发一种新的体绘制方法来训练神经SDF表示,因此即使没有掩模监督,也可以实现更准确的表面重建。NeuS在高质量的表面重建方面的性能优于现有技术,特别是对于具有复杂结构和自遮挡的对象和场景。本篇博文将根据代码执行流程解析测试阶段具体的功能模块代码。

文章目录

  • 【三维重建】【深度学习】NeuS代码Pytorch实现--测试阶段代码解析(下)
  • 前言
  • validate_mesh附加
  • interpolate_view
  • render_novel_image
  • gen_rays_between
  • 总结


前言

在详细解析NeuS网络之前,首要任务是搭建NeuS【win10下参考教程】所需的运行环境,并完成模型的训练和测试,展开后续工作才有意义。
本博文将对NeuS测试阶段涉及的剩余功能代码模块进行解析。

博主将各功能模块的代码在不同的博文中进行了详细的解析,点击【win10下参考教程】,博文的目录链接放在前言部分。

这里的代码段是exp_runner.py文件的__main__函数部分,在此前的博文中博主已经详细讲解了train模块和validate_mesh模块,本博文讲最后讲解的interpolate_view模块代码。

if args.mode == 'train':runner.train()
elif args.mode == 'validate_mesh':runner.validate_mesh(world_space=True, resolution=512, threshold=args.mcube_threshold)
elif args.mode.startswith('interpolate'):  # Interpolate views given two image indices_, img_idx_0, img_idx_1 = args.mode.split('_')img_idx_0 = int(img_idx_0)img_idx_1 = int(img_idx_1)runner.interpolate_view(img_idx_0, img_idx_1)

validate_mesh附加

在之前的博文中已经对代码进行了详细的讲解,这里只是补充说明resolution参数的作用。

runner.validate_mesh(world_space=True, resolution=512, threshold=args.mcube_threshold)

如下图所示,resolution的数值越大,提取点(体素)的数量越多,则重建效果越细致。


interpolate_view

属于exp_runner.py文件的Runner类中的成员方法,将渲染产生的图片合成视频(mp4格式)保存。

def interpolate_view(self, img_idx_0, img_idx_1):# 保存渲染的图片images = []# 渲染生成的图片帧数n_frames = 60for i in range(n_frames):print(i)# 根据图像序号,分别作为起点和终点,渲染出介意俩图片之间的图片images.append(self.render_novel_image(img_idx_0,img_idx_1,np.sin(((i / n_frames) - 0.5) * np.pi) * 0.5 + 0.5,resolution_level=4))# 将图片倒放一遍for i in range(n_frames):images.append(images[n_frames - i - 1])# 图片合成mp4格式fourcc = cv.VideoWriter_fourcc(*'mp4v')# 指定视频保存路径video_dir = os.path.join(self.base_exp_dir, 'render')os.makedirs(video_dir, exist_ok=True)h, w, _ = images[0].shape# 合成视频writer = cv.VideoWriter(os.path.join(video_dir,'{:0>8d}_{}_{}.mp4'.format(self.iter_step, img_idx_0, img_idx_1)),fourcc, 30, (w, h))for image in images:writer.write(image)writer.release()

这里还将渲染产生的图片反方向再加入列表里,所以合成的视频感觉从一点就是推过去而后又拉回来。


render_novel_image

完成NeuS模型训练后,根据俩个相机位姿渲染出从一个位姿运动到另一个位姿的过程中的多个图片,从而验证模型训练的效果。
首先需要gen_rays_between函数生成运动过程中某个位置的整张图片(下采样后)的光线rays,然后获取rays光线上采样点(前景)的最远点和最近点,最后通过renderer函数获取所需的结果。

def render_novel_image(self, idx_0, idx_1, ratio, resolution_level):"""Interpolate view between two cameras."""rays_o, rays_d = self.dataset.gen_rays_between(idx_0, idx_1, ratio, resolution_level=resolution_level)H, W, _ = rays_o.shaperays_o = rays_o.reshape(-1, 3).split(self.batch_size)rays_d = rays_d.reshape(-1, 3).split(self.batch_size)out_rgb_fine = []for rays_o_batch, rays_d_batch in zip(rays_o, rays_d):# 最近点和最远点near, far = self.dataset.near_far_from_sphere(rays_o_batch, rays_d_batch)# 背景颜色background_rgb = torch.ones([1, 3]) if self.use_white_bkgd else Nonerender_out = self.renderer.render(rays_o_batch,rays_d_batch,near,far,cos_anneal_ratio=self.get_cos_anneal_ratio(),background_rgb=background_rgb)out_rgb_fine.append(render_out['color_fine'].detach().cpu().numpy())del render_out# 渲染出图片img_fine = (np.concatenate(out_rgb_fine, axis=0).reshape([H, W, 3]) * 256).clip(0, 255).astype(np.uint8)return img_fine

gen_rays_between

Dataset数据管理器的定义的函数,在models/dataset.py文件下。博主【NeuS总览】的博文中,已经简单介绍过这个过程。

def gen_rays_between(self, idx_0, idx_1, ratio, resolution_level=1):"""Interpolate pose between two cameras.在两个摄影机之间的插值,获得新的摄影机并在世界空间中生成光线"""# idx_0是起点图像# idx_1是终点图像# 下采样倍数l = resolution_level# 理解为将图像尺寸缩放为原始输入图像尺寸的(1/l*1/l)倍tx = torch.linspace(0, self.W - 1, self.W // l)ty = torch.linspace(0, self.H - 1, self.H // l)pixels_x, pixels_y = torch.meshgrid(tx, ty)# 由像素坐标系转换到对应的空间坐标系p = torch.stack([pixels_x, pixels_y, torch.ones_like(pixels_y)], dim=-1)  # [w, h, 3]p = torch.matmul(self.intrinsics_all_inv[0, None, None, :3, :3], p[:, :, :, None]).squeeze()  # [w, h, 3]# 相机坐标下的单位方向向量rays_v = p / torch.linalg.norm(p, ord=2, dim=-1, keepdim=True)  # [w, h, 3]# 这行代码好像没啥作用trans = self.pose_all[idx_0, :3, 3] * (1.0 - ratio) + self.pose_all[idx_1, :3, 3] * ratio# idx_0图像的外参(逆)pose_0 = self.pose_all[idx_0].detach().cpu().to(self.device).numpy()# idx_1图像的外参(逆)pose_1 = self.pose_all[idx_1].detach().cpu().to(self.device).numpy()# idx_0图像的外参pose_0 = np.linalg.inv(pose_0)# idx_1图像的外参pose_1 = np.linalg.inv(pose_1)# idx_0旋转矩阵rot_0 = pose_0[:3, :3]# idx_1旋转矩阵rot_1 = pose_1[:3, :3]# 旋转矩阵表示的旋转的对象rots = Rot.from_matrix(np.stack([rot_0, rot_1]))    # [2,3,3]key_times = [0, 1]# 确定对应的时间和旋转量 2个pose对应俩个时间slerp = Slerp(key_times, rots)# 获得rot_0到rot_1的ratio的旋转矩阵rot_ratio(ratio在0~1之间)# 简单理解就是rot_0变换到rot_1的期间的中间过程rot_ratiorot = slerp(ratio)  # [3,3]# 4×4的单位矩阵pose = np.diag([1.0, 1.0, 1.0, 1.0])pose = pose.astype(np.float32)# 将旋转矩阵rot覆盖到pose对应位置上pose[:3, :3] = rot.as_matrix()# 将位移矩阵覆盖到pose对应位置上 (p1-p0)*r+p0=(1-r)*p0+p1*rpose[:3, 3] = ((1.0 - ratio) * pose_0 + ratio * pose_1)[:3, 3]# 对外参pose求逆pose = np.linalg.inv(pose)# 旋转矩阵rot = torch.from_numpy(pose[:3, :3]).cuda()# 平移矩阵trans = torch.from_numpy(pose[:3, 3]).cuda()# 世界坐标系下的单位方向向量rays_v = torch.matmul(rot[None, None, :3, :3], rays_v[:, :, :, None]).squeeze()  # [w, h, 3]# 相机光心在世界坐标系下的位置rays_o = trans[None, None, :3].expand(rays_v.shape)  # [w, h, 3]# [h, w, 3] [h, w, 3]return rays_o.transpose(0, 1), rays_v.transpose(0, 1)

代码的执行示意图如下图所示,函数返回了rays_o(光心)和rays_v(单位方向向量)。

根据俩个相机位姿算出第三个相机位姿,R和T的计算方式有点区别。R的计算借助cipy.spatial.transform.Rotation,具体原理博主是参考ChatGPT的。


总结

尽可能简单、详细的介绍NeuS测试阶段剩余代码:interpolate_view渲染合成视频。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/100781.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3D医学教学虚拟仿真系统:身临其境感受人体结构和功能

3D医学教学虚拟仿真系统是一种基于虚拟现实技术的教学工具,它可以帮助学生更好地理解和掌握医学知识。这种课件通常包括人体解剖学、生理学、病理学等方面的教学内容,通过三维立体的图像和动画展示,让学生更加直观地了解人体结构和功能。 与传…

今天七夕,群友让我帮忙给他分配一个对象,于是我。。。

今天七夕,群友让我帮忙给他分配一个对象,于是我只好尝试给他分配对象了: CGirlFrined *pGF new CGirlFrined("大屌萌妹");int nRet (群友).SetGirlFriend(pGF);if (nRet ! 0) {alert("分配失败!"); }后来觉…

交换机生成树STP

生成树协议(spanning-tree-protocol,stp):在具有物理环路的交换机网络上生成没有回路的逻辑网络的方法,生成树协议使用生成树算法,在一个具有冗余路径的容错网络中计算出一个无环路的路径,使一部分端口处于…

「UG/NX」Block UI 超级截面SuperSection

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

easyexcel合并单元格底色

一、效果图 二、导出接口代码 PostMapping("selectAllMagicExport")public void selectAllMagicExport(HttpServletRequest request, HttpServletResponse response) throws IOException {ServiceResult<SearchResult<TestMetLineFe2o3Export>> result …

【3D激光SLAM】LOAM源代码解析--transformMaintenance.cpp

系列文章目录 【3D激光SLAM】LOAM源代码解析–scanRegistration.cpp 【3D激光SLAM】LOAM源代码解析–laserOdometry.cpp 【3D激光SLAM】LOAM源代码解析–laserMapiing.cpp 【3D激光SLAM】LOAM源代码解析–transformMaintenance.cpp 写在前面 本系列文章将对LOAM源代码进行讲解…

Hadoop学习:深入解析MapReduce的大数据魔力(三)

Hadoop学习&#xff1a;深入解析MapReduce的大数据魔力&#xff08;三&#xff09; 3.5 MapReduce 内核源码解析3.5.1 MapTask 工作机制3.5.2 ReduceTask 工作机制3.5.3 ReduceTask 并行度决定机制 3.6 数据清洗&#xff08;ETL&#xff09;1&#xff09;需求2&#xff09;需求…

python实战【外星人入侵】游戏并改编为【梅西vsC罗】(球迷整活)——搭建环境、源码、读取最高分及生成可执行的.exe文件

文章目录 &#x1f3a5;前言&#x1f4bc;安装Pygame&#x1f50b;游戏的实现读写并存储【外星人入侵】游戏最高分游戏源码alien_invasion.pygame_functions.pyship.pyalien.pybullet.pybutton.pyscoreboard.pygame_stats.pysettings.py宇宙飞船和外星人的 .bmp类型文件 &#…

Java之继承详解二

3.7 方法重写 3.7.1 概念 方法重写 &#xff1a;子类中出现与父类一模一样的方法时&#xff08;返回值类型&#xff0c;方法名和参数列表都相同&#xff09;&#xff0c;会出现覆盖效果&#xff0c;也称为重写或者复写。声明不变&#xff0c;重新实现。 3.7.2 使用场景与案例…

hive表的全关联full join用法

背景&#xff1a;实际开发中需要用到全关联的用法&#xff0c;之前没遇到过&#xff0c;现在记录一下。需求是找到两张表的并集。 全关联的解释如下&#xff1b; 下面建两张表进行测试 test_a表的数据如下 test_b表的数据如下&#xff1b; 写第一个full join 的SQL进行查询…

基于 BlockQueue(阻塞队列) 的 生产者消费者模型

文章目录 阻塞队列&#xff08;BlockQueue&#xff09;介绍生产者消费者模型 介绍代码实现lockGuard.hpp&#xff08;&#xff09;Task.hpp&#xff08;任务类&#xff09;BlockQueue.hpp&#xff08;阻塞队列&#xff09;conProd.cc&#xff08;生产者消费者模型 主进程&#…

pytest自动化框架运行全局配置文件pytest.ini

还记得在之前的篇章中有讲到Pytest是目前主要流行的自动化框架之一&#xff0c;他有基础的脚本编码规则以及两种运行方式。 pytest的基础编码规则是可以进行修改&#xff0c;这就是今日文章重点。 看到这大家心中是否提出了两个问题&#xff1a;pytest的基础编码规则在哪可以…

探索高效的HTTP异步接口测试方法:从轮询等待到自动化方案

本文将深入探讨HTTP异步接口测试的多个方面&#xff0c;包括轮询等待、性能测试以及自动化方案。通过详细的解释和实际案例&#xff0c;帮助您了解如何有效地测试异步接口&#xff0c;确保系统的稳定性和性能。 在现代软件开发中&#xff0c;HTTP异步接口扮演着至关重要的角色&…

QCustomPlot绘制多条曲线在不同的位置

ui->setupUi(this);QCPLayoutGrid* layout ui->customPlot->plotLayout();//把之前的布局清除layout->clear();//设置行间距layout->setRowSpacing(0);layout->setColumnSpacing(0);// 2. 准备数据QVector<double> x(101), y(101);for (int i 0; i &…

设计模式之代理模式(Proxy)的C++实现

1、代理模式的提出 在组件的开发过程中&#xff0c;有些对象由于某种原因&#xff08;比如对象创建的开销很大&#xff0c;或者对象的一些操作需要做安全控制&#xff0c;或者需要进程外的访问等&#xff09;&#xff0c;会使Client使用者在操作这类对象时可能会存在问题&…

Bigemap在地质工程勘察行业中的应用

Bigemap在地质工程勘察行业中的应用 选择Bigemap的原因&#xff1a; 师兄在测绘局工作&#xff0c;买过全能版&#xff0c;帮我下载过高程数据&#xff0c;我觉得效果可以&#xff0c;于是联系到软件公司进行试用、咨询 使用场景&#xff1a; 影像、等高线、地形等资料下载&…

七夕表白前端代码

七夕表白前端代码&#xff0c;话不多说直接上代码&#xff1a; <!DOCTYPE html> <html> <head><title>七夕表白</title><style>body {text-align: center;font-family: Arial, sans-serif;}h1 {color: #e74c3c;}p {font-size: 18px;line-…

热烈祝贺甘肃峻茂成功入选航天系统采购供应商库

经过航天系统采购平台的严审&#xff0c;甘肃峻茂新材料科技有限公司成功入选中国航天系统采购供应商库。航天系统采购平台是航天系统内企业采购专用平台&#xff0c;服务航天全球范围千亿采购需求&#xff0c;目前&#xff0c;已有华为、三一重工、格力电器、科大讯飞等企业、…

数据分析15——office中的Excel基础技术汇总

0、前言&#xff1a; 这部分总结就是总结每个基础技术的定义&#xff0c;在了解基础技术名称和定义后&#xff0c;方便对相关技术进行检索学习。笔记不会详细到所有操作都说明&#xff0c;但会把基础操作的名称及作用说明&#xff0c;可自行检索。本文对于大部分读者有以下作用…

SpringBoot08——前端数据模拟MockJS+vue-element-admin后台集成

感觉用到再说吧 2. vue-element-admin后台集成 3.JWT跨域认证 看自己的demo2源码吧