Pytorch Lighting 库的学习 mvsplat 的笔记

变量理解:

context_image: 表示投影的 refrence image
Epipolar Transformer vs Swin Transformer : 不同于 Pixel Splat 使用的是 Epipolar Transformer. MVspalt 使用的是 Swin Transformer, 但是作者在 Code 里面 也使用了 Epipolar Transformer 并对此进行了 消融实验:

网络架构,得到 CNN_feature 和 Transformer_feature :

  • 假设 context_imgae shape : (1,2,3,256,256)
  • 进入一个 Backbone Multiview 的Encoder; 这个是 一个 CNN 的 Encoder 去提取 Image 的 feature, 进行了 4 倍的 downsampling , 对应的 cnn_features shape (1,2,128,64,64)
## CNN 提取特征
features_list = self.extract_feature(self.normalize_images(images))  # list of features
  • 对这个 Feature 添加位置信息,使用Transformer 里面的 PE, 但是不会改变 Tensor 的大小。shape (1,2,128,64,64)
    在这里插入图片描述
  • 将上面的 Tensor 送入到 Transformer 当中, 输出的 Tensor 维度不变, transformer 计算的 shape 依然是(1,2,128,64,64)

经过Transformer 网络之后,预测 3D Gaussian feature 和 深度:

  depths, densities, raw_gaussians = self.depth_predictor(in_feats,             ## transformer feature (1,2,128,64,64)context["intrinsics"],context["extrinsics"],context["near"],context["far"],gaussians_per_pixel=True,deterministic=deterministic,extra_info=extra_info,cnn_features=cnn_features,  ## CNN feature (1,2,128,64,64))

变量 refine_out:(1,32,256,256)
image:(2,3,256,256)
pro_fea_in_fullers:(2,128,256,256)

1. 在这个函数中首先进行 数据预处理:
 feat_comb_lists, intr_curr, pose_curr_lists, disp_candi_curr = (   prepare_feat_proj_data_lists(features,intrinsics,extrinsics,near,far,num_samples=self.num_depth_candidates))

主要的 功能如下:

     * 对于 depth 进行等间距的 128 个采样点.* feat_comb_lists 第0个元素是 [0,1] 排列的 transformer feature  feature_01; 第1个元素是 [1,0] 排列的 transformer feature feature_10 ;* 对于 re10k format 的内参 unnormalize*  pose_curr_lists 分别是 0->1 的位姿变换和 1->0 的位姿变换
2. 构建两个 Feature 的 Cost Volume:

feat10: 第一个元素是feature map 1; 第2个元素是feature map 2
pose_curr: 第一个元素是camera 1 -> camera 0 的 Transform ; 第2个元素是camera 0 -> camera 1 的 Transform

2.1 作用: 将feature map 1 根据深度 lift 成一个 3D Volume, 然后根据 Pose 将 3D 点投影到 image 0 的 2D 平面上 interpolate feature.

 for feat10, pose_curr in zip(feat_comb_lists[1:], pose_curr_lists):# 1. project feature1  to camera0 and project feture0 to camera 1# feat10: [0] is feature map 1;  [1] is feature map 0feat01_warped = warp_with_pose_depth_candidates(feat10,intr_curr,pose_curr,1.0 / disp_candi_curr.repeat([1, 1, *feat10.shape[-2:]]),warp_padding_mode="zeros",)  # [B, C, D, H, W] [2, 128, 128, 64, 64] 表示 128,64,64 个3D点 投影到2D平面上query 的feature. 每个feature 的 维度是 128维度

在这里插入图片描述

2.2 根据 不同的 depth 投影得到的 featuure 和原始的 feature 计算 点积 (相似度),然后对于 feature channel 那一个维度 求取 sum

raw_correlation_in = (feat01.unsqueeze(2) * feat01_warped).sum(1) / (c**0.5)  # [vB, D, H, W]

在这里插入图片描述

2.3 使用2D U-Net 进行 CostVolume 的 Refine, 再使用Softmax 函数 估计 出每一个 采样 Depth的 权重。 (准确的Depth 权重应该最大)
   pdf = F.softmax(self.depth_head_lowres(raw_correlation), dim=1)  # [2xB, D, H, W]

在这里插入图片描述

2.4 SoftMax 得到的权重和 depth_candi 点积,可以得到 depth 的预测,然后上采样到原始分辨率
 coarse_disps = (disp_candi_curr * pdf).sum(dim=1, keepdim=True)  # (vb, 1, h, w)fullres_disps = F.interpolate(coarse_disps,scale_factor=self.upscale_factor,mode="bilinear",align_corners=True,)

coarse_disps :(2,1,64,64) 是feature map 的图像 的 Dpeth 预测
fullres_disps :(2,1,256,256) 是原始 Resolution 的图像 的 Dpeth 预测

2.5 对于预测的 Depth 使用 2DU-Net 进行Refine, 得到feature volume。
refine_out = self.refine_unet(torch.cat((extra_info["images"], proj_feature, fullres_disps, pdf_max), dim=1))

最后的 refine depth 是 fullres_disps + delta_disps

   fine_disps = (fullres_disps + delta_disps).clamp(1.0 / rearrange(far, "b v -> (v b) () () ()"),1.0 / rearrange(near, "b v -> (v b) () () ()"),)

refine_out :(2,32,256,256) 是输入U-Net 得到的feature, 是32通道

2.6 利用 Transformer feature, CNN feature, Depth 的预测 和 原始的color 图像, 得到 Gaussian 的 feature map

这个 self. to_gaussians 是一个 两层的 CNN。 输入c=163, 输出 c=84

 # gaussians head
raw_gaussians_in = [refine_out, extra_info["images"], proj_feat_in_fullres]
raw_gaussians_in = torch.cat(raw_gaussians_in, dim=1)
raw_gaussians = self.to_gaussians(raw_gaussians_in) 

输出raw_gaussians (2,84,256,256), 原始分辨率的 Gaussian feature map



下面是各种 Gaussian 属性的 预测 :

1. Opcaity 的 预测

对前面得到的 Costvolume 进行卷积。
输入是 refine_out:(1,32,256,256), 通过卷积 变成2个通道,其中一个作为 density, 另一个作为 视差。 文章的解释: matching volume 里面 对应关系越强,那么 density 越大

delta_disps_density = self.to_disparity(refine_out)
delta_disps, raw_densities = delta_disps_density.split(gaussians_per_pixel, dim=1)# combine coarse and fine info and match shape
densities = repeat(F.sigmoid(raw_densities),"(v b) dpt h w -> b v (h w) srf dpt",b=b,v=v,srf=1,
)

之后将 density 转成opacity, 转换通过一个构造函数进行的:
y = { 0 < x < 1 : 0.5 ⋅ ( 1 − ( 1 − x ) t + x 1 t ) } y = \left\{0<x<1: 0.5 \cdot\left(1-(1-x)^t+x^{\frac{1}{t}}\right)\right\} y={0<x<1:0.5(1(1x)t+xt1)}
在这里插入图片描述

2. Center 的 预测

每一个 pixel 生成一个坐标, 对应一个 Gaussian. Pixel 发生光线,根据 depth 反投影得到 Gaussian 的 Center.. 并不一定是从 像素 中点 发生光心, 因此,每一个 pixel 还有一个 2D 的offset 偏移量· offset_xy ,也是泛化得到的,从 raw_gaussians (2,84,256,256) 的前2个channel 生成。

offset_xy = gaussians[..., :2].sigmoid()  
pixel_size = 1 / torch.tensor((w, h), dtype=torch.float32, device=device)
xy_ray = xy_ray + (offset_xy - 0.5) * pixel_size means = origins + directions * depths[..., None]

3. Scale 的 预测

Scale 由 前3 个channel 确定,还需要和 depth 以及相机内参数有关系。 需要注意一下2点:

  1. Regarding multiplying by depths, further objects will be smaller when projected.
  2. Regarding multiplying by multiplier. This operation constrains the Gaussian scale concerning the pixel width in the image space, which
    aims to ensure that the Gaussian scale with scale 1 is roughly the
    same as 1 pixel in the image space.
scales = scale_min + (scale_max - scale_min) * scales.sigmoid()
h, w = image_shape
pixel_size = 1 / torch.tensor((w, h), dtype=torch.float32, device=device)
multiplier = self.get_scale_multiplier(intrinsics, pixel_size)
scales = scales * depths[..., None] * multiplier[..., None]

4. Covariance 的 预测

Rotations 是由 raw_gaussians 的4个通道预测的,先得到四元数。 之后再和 Scale 构成 协方差矩阵, 注意: 这里的 协方差矩阵是 camera 系下面的,还需要外参转到 world 坐标系

rotations = rotations / (rotations.norm(dim=-1, keepdim=True) + eps)
covariances = build_covariance(scales, rotations)
c2w_rotations = extrinsics[..., :3, :3]
covariances = c2w_rotations @ covariances @ c2w_rotations.transpose(-1, -2)

4. SH 的 预测

剩下的 75个 channel 对应着 SH 系数
opacity 的生成 在 传入下面的函数之前已经生成了,是将 density 转换成 Gaussian 的 Opacity

 # 得到SH系数
sh = rearrange(sh, "... (xyz d_sh) -> ... xyz d_sh", xyz=3)
sh = sh.broadcast_to((*opacities.shape, 3, self.d_sh)) * self.sh_mask

根据上面的属性,得到 泛化的 Gaussian

return Gaussians(means=means,covariances=covariances,harmonics=rotate_sh(sh, c2w_rotations[..., None, :, :]),opacities=opacities,# NOTE: These aren't yet rotated into world space, but they're only used for# exporting Gaussians to ply files. This needs to be fixed...scales=scales,rotations=rotations.broadcast_to((*scales.shape[:-1], 4)),)

生成当前场景的 3DGS 之后,在 Target View 上进行 Render

Pytorch Lighting 的基础知识:

Train 的主函数: training_step 函数:
Test 的主函数: test_step 函数:

Test 的 dataloader 的主函数:
val_dataloader 函数
test_dataloader 函数

数据Dataset 类 全部在 dataset_re10k.py 这个文件

  def test_dataloader(self, dataset_cfg=None):##主要用来 读取的数据文件都在   .torchdataset = get_dataset(self.dataset_cfg if dataset_cfg is None else dataset_cfg,"test",self.step_tracker,) dataset = self.dataset_shim(dataset, "test")return DataLoader(dataset,self.data_loader_cfg.test.batch_size,num_workers=self.data_loader_cfg.test.num_workers,generator=self.get_generator(self.data_loader_cfg.test),worker_init_fn=worker_init_fn,persistent_workers=self.get_persistent(self.data_loader_cfg.test),shuffle=False,)

MVSplat 是加载 chunk 进行实验的:

每一个 chunk 是由 一个 xx.torch 文件加载过来的:

chunk = torch.load(chunk_path)

每一个 chunk 里面有 5个 dtu数据集, 每一个数据集里面存放着 45 张图像, 而每一个 数据集的以字典的形式进行存放。 如下所示,里面存放在 图像的 camera, image 和 数据集的名称 “key”. ycamera 从 “camera” 读取随机一个场景的 内外参数:example 是 chunk 里面的某一个数据集:

 extrinsics, intrinsics = self.convert_poses(example["cameras"])之后 读取图像。

因此,代码里有两个 for loop, 一个 循环 .torch 文件, 一个 循环 torch 文件里面的数据集。

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

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

相关文章

容器项目之前后端分离

容器化部署ruoyi项目 #需要的镜像nginx、java、mysql、redis、 #导入maven镜像、Java镜像和node镜像 docker load -i java-8u111-jdk.tar docker load -i maven-3.8.8-sapmachine-11.tar docker load -i node-18.20.3-alpine3.20.tar #拉取MySQL和nginx镜像 docker pull mysql…

echarts学习:基本使用和组件封装

前言 我在工作中使用echarts较少&#xff0c;这就导致每次使用时都要从头再来&#xff0c;这让我很头疼。因此我决心编写一系列文章将我参与工作后几次使用echarts所用到的知识记录下来&#xff0c;以便将来可以快速查阅。 一、基本使用 像我一样的新手&#xff0c;想要入门e…

PyCharm中快速搭建Python虚拟环境的指南

在 PyCharm 中创建一个新的 Python 虚拟环境可以帮助你为不同的项目管理不同的依赖包&#xff0c;避免版本冲突。以下是在 PyCharm 中创建虚拟环境的步骤&#xff1a; 打开或创建一个项目: 如果你还没有打开 PyCharm&#xff0c;首先打开它&#xff0c;然后选择“Open”打开一个…

【Java】还有人不懂继承?25 个 Case 包教包会

还有人不懂继承&#xff1f;25 个 Case 包教包会 1.Implement single inheritance2.Implement multilevel inheritance3.Implement hierarchical inheritance4.Override a base class method into a derived class5.Demonstrate the protected access specifier6.Create an Stu…

开发电商系统的技术选型

开发电商系统是一个复杂的任务&#xff0c;需要全面的技术选型来确保系统的稳定性、可扩展性和性能。本文将详细探讨在开发电商系统时涉及的各方面技术选型&#xff0c;包括架构设计、前端技术、后端技术、数据库选择、缓存策略、安全性、支付系统、日志和监控、以及自动化运维…

RN的安卓和iOS打包步骤(软件托管平台推荐)

安卓 官方中文网网址 步骤 1.在项目/android/app下面运行如下终端命令 keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000<

《面试笔记》——MySQL终结篇30

三大范式&#xff1f; 第一范式&#xff1a;字段具有原子性&#xff0c;不可再分&#xff08;字段单一职责&#xff09; 第二范式&#xff1a;满足第一范式&#xff0c;每行应该被唯一区分&#xff0c;加一列存放每行的唯一标识符&#xff0c;称为主键&#xff08;都要依赖主…

10- Redis 键值对数据库是怎么实现的?

在开始将数据结构之前&#xff0c;先给介绍下 Redis 是怎样实现键值对&#xff08;key-value&#xff09;数据库的。 Redis 的键值对中的 key 就是字符串对象&#xff0c;而 value 可以是字符串对象&#xff0c;也可以是集合数据类型的对象&#xff0c;比如 List 对象&#xf…

Django序列化器中is_valid和validate

今天上班的时候分配了一个任务&#xff0c;是修复前端的一个提示优化&#xff0c;如下图所示&#xff1a; 按照以往的经验我以为可以直接在validate上进行校验&#xff0c;如何抛出一个异常即可 &#xff0c;例如&#xff1a; class CcmSerializer(serializers.ModelSerialize…

体验Photoshop:无需下载,直接在浏览器编辑图片

搜索Photoshop时&#xff0c;映入眼帘的是PS软件下载&#xff0c;自学PS软件需要多长时间&#xff0c;学PS软件有必要报班吗...PS软件的设计功能很多&#xff0c;除了常见的图像处理功能外&#xff0c;还涉及图形、文本、视频、出版等。不管你是平面设计师&#xff0c;UI/UX设计…

字节算法岗二面秒挂,效率真高。。。

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接…

Servlet搭建博客系统

现在我们可以使用Servlet来搭建一个动态(前后端可以交互)的博客系统了(使用Hexo只能实现一个纯静态的网页,即只能在后台自己上传博客)。有一种"多年媳妇熬成婆"的感觉。 一、准备工作 首先创建好项目,引入相关依赖。具体过程在"Servlet的创建"中介绍了。…

FreeRTOS【14】软件定时器使用

1.开发背景 基于以上的章节&#xff0c;这个篇章主题是软件定时器使用&#xff0c;能使用 FreeRTOS 的基本都是从裸机 MCU 过来的&#xff0c;基本都知道 MCU 最基本的功能之一就是定时器&#xff0c;确切的说是硬件定时器&#xff0c;外围电路已经构建好的&#xff0c;精度很高…

bug 定位tag

mega: 解压所有log 命令 extract_and_rename . 播放 tag&#xff1a;MediaServiceConnection、BluetoothMediaBrowserService、PlaybackManager、MediaPlayEventListener message: AudioFocus、onPlaybackStateChanged:PlaybackState {state 网易云播放sdk问题&#xf…

【实战JVM】-实战篇-05-内存泄漏及分析

【实战JVM】-实战篇-05-内存泄漏及分析 1 内存溢出和内存泄漏1.1 常见场景1.2 解决内存溢出的方法1.2.1 发现问题1.2.1.1 top1.2.1.2 ViusalVM1.2.1.3 arthas1.2.1.4 PrometheusGrafana 1.2.2 堆内存状况对比1.2.3 内存泄漏原因-代码中1.2.3.1 equals()-hashCode()1.2.3.2 内部…

小程序-富文本编辑框的注意事项

富文本编辑框官网位置 表单组件 / editor (qq.com)https://developers.weixin.qq.com/miniprogram/dev/component/editor.html &#xff08;一&#xff09;富文本编辑框的作用 1.适用于一些表单的提交 2.这些表单内容需要自定义图片大小&#xff0c;编辑文字样式 主要用到的是…

MySQL分页:ROW_NUMBER() vs LIMIT

在 MySQL 中&#xff0c;实现数据分页的方法主要有两种&#xff1a;使用 ROW_NUMBER() 窗口函数和使用 LIMIT 子句。本文将探讨这两种方法的优劣&#xff0c;帮助您选择最适合您的场景。 1. ROW_NUMBER() 分页 ROW_NUMBER() 是 MySQL 8.0 及以上版本支持的窗口函数&#xff0…

【C++】10.list

list这个迭代器是双向迭代器&#xff0c;与vector的迭代器具有很大的区别&#xff0c;主要在于双向迭代器不支持&#xff0b;- 操作 正由于list的双向迭代器&#xff0c;因此<algorithm>中的sort()函数无法使用&#xff0c;list单独实现了一个sort()函数&#xff0c;但效…

[力扣题解] 151. 反转字符串中的单词

题目&#xff1a;151. 反转字符串中的单词 思路 代码 Method 1&#xff0c;Me class Solution { public:string reverseWords(string s) {int i, start;// Step 1for(i 0; i < s.size() - 1; i){if(s[i] && s[i 1] ){s.erase(i 1, 1);i--;}}// Step 2if…

统计信号处理基础 习题解答10-5

题目 通过令 并进行计算来重新推导MMSE估计量。提示&#xff1a;利用结果 解答 首先需要明确的是&#xff1a; 上式是关于观测值x 的函数 其次需要说明一下这个结果 和教材一样&#xff0c;我们用求期望&#xff0c;需要注意的是&#xff0c;在贝叶斯情况下&#xff0c;是个…