【视点合成】代码解读:生成demo视频

变换工具

def render_3dphoto(src_imgs,          # 输入的源图像,维度为 [batch_size, 3, height, width]mpi_all_src,       # 输入的所有源图像的MPI,维度为 [batch_size, num_planes, 4, height, width]disparity_all_src, # 所有源图像的视差信息,维度为 [batch_size, num_planes]k_src,             # 源相机的内参矩阵,维度为 [batch_size, 3, 3]k_tgt,             # 目标相机的内参矩阵,维度为 [batch_size, 3, 3]save_path,         # 渲染视频的保存路径
):

disparity 也就是深度。

单应性变换

使用HomographySample变换。utils.mpi.homography_sampler.HomographySample


class HomographySample:"""处理与单应性变换相关的操作,它提供了生成二维网格坐标的功能,计算平面法线,以及将欧拉角转换为旋转矩阵"""def __init__(self, H_tgt, W_tgt, device=None):if device is None:self.device = torch.device("cpu")else:self.device = deviceself.Height_tgt = H_tgtself.Width_tgt = W_tgtself.meshgrid = self.grid_generation(self.Height_tgt, self.Width_tgt, self.device)  # 生成目标图像的二维网格坐标self.meshgrid = self.meshgrid.permute(2, 0, 1).contiguous()  # 3xHxW   对生成的网格进行维度重排,以匹配 3xHxW 的形状self.n = self.plane_normal_generation(self.device)  # 生成平面法线

其中方法:

def euler_to_rotation_matrix(x_angle, y_angle, z_angle, seq='xyz', degrees=False):"""将欧拉角转换为旋转矩阵Note that here we want to return a rotation matrix rot_mtx, which transform the tgt points into src frame,i.e, rot_mtx * p_tgt = p_srcTherefore we need to add negative to x/y/z_angle  由于在欧拉角中,旋转是绕坐标轴的正方向进行的,而我们希望进行的是相反方向的旋转,因此需要对 x/y/z 分量的欧拉角添加负号,以实现从目标点到源坐标系的变换。注意 **这里的欧拉角需要取反,因为我们希望得到的旋转矩阵是将目标点变换到源坐标系的旋转**  https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.transform.Rotation.html:param roll::param pitch::param yaw::return:"""r = Rotation.from_euler(seq,[-x_angle, -y_angle, -z_angle],degrees=degrees)rot_mtx = r.as_matrix().astype(np.float32)# 用于图像的单应性变换,其中 meshgrid 用于定义原始图像中每个像素的坐标,plane_normal_generation 用于定义平面法线(对于单应性变换而言通常是不必要的,但可能用于其他3D变换),# euler_to_rotation_matrix 则用于根据给定的欧拉角生成对应的旋转矩阵。这些操作都是在准备实施单应性变换或其他相关图像几何变换的数据和参数。return rot_mtx

映射前定义网格

@staticmethoddef grid_generation(H, W, device):""":生成网格坐标,用于后续的映射计算。"""# 使用 numpy 生成x和y方向的线性等分点,并通过 np.meshgrid 生成一个二维网格x = np.linspace(0, W - 1, W)y = np.linspace(0, H - 1, H)xv, yv = np.meshgrid(x, y)  # HxWxv = torch.from_numpy(xv.astype(np.float32)).to(dtype=torch.float32, device=device)yv = torch.from_numpy(yv.astype(np.float32)).to(dtype=torch.float32, device=device)# 生成一个全为1的张量,与x和y坐标一起堆叠(通道维度)成3通道的网格坐标张量ones = torch.ones_like(xv)meshgrid = torch.stack((xv, yv, ones), dim=2)  # HxWx3return meshgrid@staticmethoddef plane_normal_generation(device):"""创建一个表示垂直于xy平面(即z轴方向)的法线向量的张量"""n = torch.tensor([0, 0, 1], dtype=torch.float32, device=device)return n

使用

utils.utils.render_novel_view中:

  1. 计算深度
  2. 计算视点变换
  3. 执行变换
  4. 帧序列到视频
def render_novel_view(mpi_all_rgb_src,mpi_all_sigma_src,disparity_all_src,G_tgt_src,K_src_inv,K_tgt,homography_sampler,
):"""mpi_all_rgb_src,        # 来源视角的RGB图像集合mpi_all_sigma_src,      # 来源视角的不透明度(sigma)集合disparity_all_src,      # 来源视角的视差图集合G_tgt_src,              # 目标视角到来源视角的变换矩阵K_src_inv,              # 来源视角的相机内参矩阵的逆矩阵K_tgt,                  # 目标视角的相机内参矩阵homography_sampler,     # 用于生成和采样单应性(Homographies)的工具"""# 从源视角的视差图计算出每个平面上点的3D坐标xyz_src_BS3HW = mpi_rendering.get_src_xyz_from_plane_disparity(homography_sampler.meshgrid,disparity_all_src,K_src_inv)# 使用源视角的3D坐标和从目标视角到源视角的变换矩阵 G_tgt_src 来计算目标视角的3D坐标xyz_tgt_BS3HW = mpi_rendering.get_tgt_xyz_from_plane_disparity(xyz_src_BS3HW,G_tgt_src)# 调用 render_tgt_rgb_depth 函数,将源视角的RGB图像、不透明度、视差图和3D坐标映射到目标视角,生成合成的目标视角图像 tgt_imgs_syntgt_imgs_syn, _, _ = mpi_rendering.render_tgt_rgb_depth(homography_sampler,mpi_all_rgb_src,mpi_all_sigma_src,disparity_all_src,xyz_tgt_BS3HW,G_tgt_src,K_src_inv,K_tgt,use_alpha=False,is_bg_depth_inf=False,)return tgt_imgs_syn

生成

函数入口

def render_3dphoto(src_imgs,  # [b,3,h,w]mpi_all_src,  # [b,s,4,h,w]disparity_all_src,  # [b,s]k_src,  # [b,3,3]k_tgt,  # [b,3,3]save_path,
):"""src_imgs,          # 输入的源图像,维度为 [batch_size, 3, height, width]mpi_all_src,       # 输入的所有源图像的MPI,维度为 [batch_size, num_planes, 4, height, width]disparity_all_src, # 所有源图像的视差信息,维度为 [batch_size, num_planes]k_src,             # 源相机的内参矩阵,维度为 [batch_size, 3, 3]k_tgt,             # 目标相机的内参矩阵,维度为 [batch_size, 3, 3]save_path,         # 渲染视频的保存路径"""h, w = mpi_all_src.shape[-2:]device = mpi_all_src.devicehomography_sampler = HomographySample(h, w, device)  # 生成单应性变换k_src_inv = torch.inverse(k_src)    # 计算源相机内参矩阵的逆矩阵,用于从像素坐标到相机坐标系的转换。# preprocess the predict MPI# 将视差信息转换为3D空间坐标xyz_src_BS3HW = mpi_rendering.get_src_xyz_from_plane_disparity(     homography_sampler.meshgrid,disparity_all_src,k_src_inv,)# 分离通道mpi_all_rgb_src = mpi_all_src[:, :, 0:3, :, :]  # BxSx3xHxWmpi_all_sigma_src = mpi_all_src[:, :, 3:, :, :]  # BxSx1xHxW# 调用一个渲染函数,用于计算从MPI合成图像时使用的混合权重_, _, blend_weights, _ = mpi_rendering.render(mpi_all_rgb_src,mpi_all_sigma_src,xyz_src_BS3HW,use_alpha=False,is_bg_depth_inf=False,)# 混合权重来更新源图像的MPI RGB部分,这里使用的是alpha blending算法mpi_all_rgb_src = blend_weights * src_imgs.unsqueeze(1) + (1 - blend_weights) * mpi_all_rgb_src# render novel views# 定义通过改变相机外参来模拟相机移动的参数。同时初始化一个空列表用于存储渲染出的帧。swing_path_list = gen_swing_path()frames = []# for cam_ext in tqdm(swing_path_list):# 利用render_novel_view函数来渲染从新视角看到的图像。这个函数需要当前的MPI RGB数据、透明度数据、视差数据、目标相机的外参(这里假设cam_ext是外参# ,cam_ext.cuda()将外参移动到GPU上)、源相机的内参矩阵的逆以及目标相机的内参矩阵。homography_sampler可能用于计算在新视角下图像的单应性变换。for cam_ext in swing_path_list:frame = render_novel_view(mpi_all_rgb_src,mpi_all_sigma_src,disparity_all_src,cam_ext.cuda(), # 目标视角到来源视角的变换矩阵k_src_inv,k_tgt,          #  目标视角的相机内参矩阵homography_sampler,)# 张量转换为NumPy数组,并进行必要的排列以匹配图像的形状要求。然后它将像素值缩放到0-255范围,并转换为uint8类型frame_np = frame[0].permute(1, 2, 0).contiguous().cpu().numpy()  # [b,h,w,3]frame_np = np.clip(np.round(frame_np * 255), a_min=0, a_max=255).astype(np.uint8)frames.append(frame_np)rgb_clip = ImageSequenceClip(frames, fps=30)# moviepy库的ImageSequenceClip类将帧列表转换成视频剪辑,设置每秒帧数为30。然后调用write_videofile方法将视频保存到指定的save_path路径# 使用mpeg4编解码器,不显示详细信息,设置比特率为3000kbps。rgb_clip.write_videofile(save_path, verbose=False, codec='mpeg4', logger=None, bitrate='3000k')

获取移动路径

def gen_swing_path(num_frames=90, r_x=0.14, r_y=0.0, r_z=0.10):"""生成一个摆动路径.生成一系列的4x4变换矩阵,每个矩阵代表了不同时间点的位置num_frames 表示要生成的帧数,默认为90帧;r_x、r_y 在x、y方向上的摆动半径r_z 表示z轴方向上的摆动半径"""# 创建了一个从01等间距的一维张量 t。这个张量表示从摆动开始到结束的时间线索引t = torch.arange(num_frames) / (num_frames - 1)# 创建了一个4x4的单位矩阵(identity matrix),然后将其重复 num_frames 次,用来存储最终生成的每一帧的变换矩阵。poses = torch.eye(4).repeat(num_frames, 1, 1)# 计算了在x轴上的摆动,使用正弦函数来生成x轴的平移部分,摆动的幅度由 r_x 确定# 正余弦: 需要一个物体的运动从最大幅度开始并且回到最大幅度poses[:, 0, 3] = r_x * torch.sin(2. * math.pi * t)poses[:, 1, 3] = r_y * (torch.cos(2. * math.pi * t)  )poses[:, 2, 3] = r_z * (torch.cos(2. * math.pi * t) - 1.0)  # 减去了1,这样摆动的起始点会更低return poses.unbind()   # 张量 poses 拆分成一个元组,元组中的每个元素是一个4x4矩阵,代表了每一帧的变换矩阵

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

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

相关文章

【Python】从文本中提取数字

使用以下正则表达式的下列模式用以提取文本中包含的数字: pattern r[^\-\d]*([-]?\d([.,]\d)?).*模式 1:正整数 text 123 result re.match(pattern, text) print(result[1]) # > 123text 123 result re.match(pattern, text) print(result[…

【博士论文写作 笔记01】绪论的写作

文章目录 1.1 研究背景与意义1.2 国内外研究现状1.3 主要研究内容1.4 本文组织架构 1.1 研究背景与意义 介绍本文研究的需求 行业现状:首先介绍一下课题涉及的行业是怎样的蓬勃发展。新问题:由于这种蓬勃发展带来了什么样的新问题。总结句:…

太阳能电池效能IV测试PV检测太阳光模拟器

目录 概述 一、系统组成 产品特点: 技术参数 数字源表 本系统支持Keithley24xx系列源表 标准太阳能电池 低阻测试夹具 自动化测试软件 概述 太阳能光伏器件的所有性能表征手段中,IV特性测试无疑是最直观、最有效、最被广泛应用的一种…

【OS】操作系统总复习笔记

操作系统总复习 文章目录 操作系统总复习一、考试题型1. 论述分析题2. 计算题3. 应用题 二、操作系统引论(第1章)2.1 操作系统的发展过程2.2 操作系统定义2.3 操作系统的基本特性2.3.1 并发2.3.2 共享2.3.3 虚拟2.3.4 异步 2.4 OS的功能2.5 OS结构2.5 习…

Android studio 按键控制虚拟LED

一、activity_main.xml代码&#xff1a; <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"http://schemas.a…

《Linux C编程实战》笔记:进程操作之创建进程

进程是一个动态的实体&#xff0c;是程序的一次执行过程。进程是操作系统资源分配的基本单位。 以下是一些概念&#xff0c;我就直接抄书了 进程是操作系统的知识&#xff0c;简单理解的话&#xff0c;你写的代码运行起来算一个进程&#xff1f; 创建进程 每个进程由进程ID号…

GPT-4.5!!!

GPT-4 还没用明白&#xff0c;GPT-4.5 就要发布了。 最近&#xff0c;OpenAI 泄露了 GPT-4.5 的发布页面&#xff0c;除了进一步增强复杂推理和跨模态理解&#xff0c;GPT-4.5 增加了一个更加强大的功能——3D。 3D 功能的进一步支持&#xff0c;也就意味着多模态最后一块版图…

工作中git工具分支和主干合并

克隆下载一个现有的 Git 仓库到本地 git clone ssh仓库地址下载后查看工作区状态包括哪些文件被修改、新增或删除等。 git status在本地建立我自己的分支&#xff08;取名Bms-Dev&#xff09;或者切换到指定的分支&#xff0c;才能提交到远程仓库上Bms-Dev的分支 git checko…

关于前端学习的思考-浮动元素嵌套块级元素12.18

1、块级元素嵌套浮动元素 先摆图片&#xff0c;当橘色的盒子高度减少的时候&#xff0c;NK AD TB PK NN并不会减少。如何解决呢&#xff1f; 加一个overflow&#xff1a;clip或者hidden 2、浮动元素嵌套块级元素 加一个overflow&#xff1a;clip或者hidden 综上所述&#xff0…

giee 添加公匙 流程记录

一、安装 百度网盘CSDN4文件夹下&#xff0c;或者官网下载&#xff1a;https://git-scm.com/downloads 二、生成密钥 1.右击打开git bash 2.$ ssh-keygen -t rsa -C “个人邮箱地址”&#xff0c;按3个回车&#xff0c;密码为空。 3.在C:\Users{windows用户名}.ssh目录下得到…

[Ray Tracing in One Weekend] 笔记

前言 本文参照自raytracing in one weekend教程&#xff0c;地址为&#xff1a;https://raytracing.github.io/books/RayTracingInOneWeekend.html 什么是光线追踪&#xff1f; 光线追踪模拟现实中的成像原理&#xff0c;通过模拟一条条直线在场景内反射折射&#xff0c;最终…

Poco SendHttpRequest PocoServer 2021-03-31

PocoServer // PocoHttpServer.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <Poco/Net/HTTPRequestHandler.h> #include <Poco/Net/HTTPRequestHandlerFactory.h> #include <Poco/Net/HTTPServerRequest.h> #include <…

面试题:vue3获取dom的方式

在 Vue 3 中&#xff0c;可以通过以下几种方式来获取 DOM 元素&#xff1a; 使用 ref&#xff1a;ref 是 Vue 3 中新增的响应式引用对象。可以通过给 DOM 元素添加 ref 属性来创建一个 ref 对象&#xff0c;并使用该对象来获取 DOM 元素的引用。 <template><div ref…

算法——分治

思想&#xff1a;分而治之&#xff0c;将大问题转化为若干个相同或相似的子问题。快排的题目常见的方法是利用三指针法将数组分三块搭配随机选择基准元素的思想 颜色分类&#xff08;分治_快排&#xff09; 颜色分类 题目解析 原地对它们进行排序&#xff0c;使得相同颜色的元…

Oracle-应用会话集中在RAC集群一个节点问题

问题&#xff1a; 用户一套Oracle19c RAC集群&#xff0c;出现一个奇怪的现象&#xff0c;通过SCAN IP访问的连接会话都集中在节点一实例&#xff0c;而且用户并没有做任何的节点服务访问去控制会话的连接节点&#xff0c;比如常见的通过集群的高可用服务去控制应用访问连接集中…

Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)

目录 一、前言 二、基于注解配置Bean 1.基本介绍 : 2.应用实例 : 3.注意事项 : 三、手动实现Spring 注解配置机制 1.需求 : 2.思路 : 3.实现 : 3.1 自定义注解类 3.2 自定义配置类 3.3 自定义容器类 3.4 在测试类中进行测试 四、自动装配 0.总述 : 1.AutoWired自动装…

LeetCode力扣每日一题(Java):69、x 的平方根

一、题目 二、解题思路 1、 我的思路 我的思路是直接循环暴力破解&#xff0c;定义计数器i&#xff0c;从1开始递增&#xff0c;直到i*i大于或等于x 于是有了如下代码 int i 1;while(true){if(i*i<x){i;}else if(i*ix){return i;}else{return i-1;}} 但提交之后超出了…

亚马逊、target、eBay、沃尔玛等平台采退、下卡,技术技巧大揭秘

今天想和大家分享一些关于做测评、采退和撸卡项目时所需的防关联和防封号环境的底层技术原理。这些内容相对比较复杂&#xff0c;相信很少有人能够完全掌握&#xff0c;因为涉及到一些比较高级的IT技术原理。 如果正在考虑开始做采退或者撸卡项目&#xff0c;或者已经在进行相…

libxls - 编译

文章目录 libxls - 编译概述笔记静态库工程测试控制台exe工程测试备注备注END libxls - 编译 概述 想处理.xls格式的excel文件. 查了一下libxls库可以干这个事. 库地址 https://github.com/libxls/libxls.git 但是这个库的makefile写的有问题, 在mingw和WSL下都编译不了. 好在…

高德地图绘制区域的地理围栏

官网示例 https://lbs.amap.com/demo/javascript-api-v2/example/overlayers/polygon-draw/ <!doctype html> <html> <head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta …