pyrender复现pytorch3d渲染结果

pyrender复现pytorch3d渲染结果

  • 一、写在前面
    • 1.1 pyrender渲染时间 ≈ 0.02s
    • 1.2 Pytorch3D渲染时间 ≈ 4s
  • 二、pytorch3d的渲染函数
    • 2.1 PyTorch3D 库创建了一个颜色渲染器(color_renderer)对象,并配置了相机、光照和渲染设置。
    • 2.2 PyTorch3D 库创建了一个 OpenGL 透视相机(OpenGLPerspectiveCameras)对象,并配置了相机的姿态。
  • 三、pyrender渲染函数
    • 3.1 关键代码
    • 3.2 完整代码
  • 省流:pyrender用PerspectiveCamera替换pytorch3d的OpenGLPerspectiveCameras,加上相机平移和相机垂直视角即可

一、写在前面

三维结果的可视化是很重要的一个工作,目前的三维渲染库,opendr(早期论文)、pyrender、pytorch3d。在我当前的任务上是要在本地电脑window上制作一个3D标注软件,仅有Cpu,我需要一个相对实时的效果,pytorch3d渲染256x256的图像需要3-5s,pyrender的渲染速度cpu上比pytorch3d快近100倍只需要0.01-0.03s。

1.1 pyrender渲染时间 ≈ 0.02s

在这里插入图片描述

1.2 Pytorch3D渲染时间 ≈ 4s

在这里插入图片描述

参考信息
pyrender 文档
pytorch3d 文档
Converting camera matrices from OpenCV / Pytorch3D #228
why pyrender and pytorch3d cpu render so slow #188
https://github.com/lucasjinreal/realrender
difference between rendering using PyTorch3d and Pyrender #1291

二、pytorch3d的渲染函数

2.1 PyTorch3D 库创建了一个颜色渲染器(color_renderer)对象,并配置了相机、光照和渲染设置。

首先,PointLights 类用于创建光照对象,其中 location 参数指定了光源的位置。在这个示例中,光源位于三维空间的原点 [0.0, 0.0, 3.0]。
然后,RasterizationSettings 类用于配置光栅化(rasterization)的设置,包括图像大小、模糊半径和每像素面片数等。在这个示例中,image_size 参数设置了图像的大小(越大,渲染时间越长),blur_radius 参数设置为 0.0 表示不进行模糊处理,faces_per_pixel 参数设置为 1 表示每个像素只考虑一个面片(整数,越大渲染时间越长)。
接下来,创建 MeshRenderer 对象,其中的 rasterizer 参数使用了 MeshRasterizer 类,并传递了相机和光栅化设置。这意味着渲染器将使用指定的相机和光栅化设置进行渲染。
最后,shader 参数使用了 HardPhongShader 类,并传递了相机和光照对象。这表示颜色渲染器将使用指定的相机和光照设置来应用硬质光照模型。

2.2 PyTorch3D 库创建了一个 OpenGL 透视相机(OpenGLPerspectiveCameras)对象,并配置了相机的姿态。

首先,look_at_view_transform 函数用于生成相机的旋转矩阵 R 和平移向量 T,以实现相机的视角和位置。在这个示例中,函数的参数为 2.7, 0, 0,表示相机所看的目标点在三维空间中的坐标为 (2.7, 0, 0)
然后,创建了一个 OpenGL 透视相机对象 OpenGLPerspectiveCameras,输入旋转矩阵 R 和平移向量 T。这将使用指定的姿态来配置相机。

# Data structures and functions for rendering
import torch
import torch.nn.functional as F
from scipy.io import loadmat
import numpy as np

from pytorch3d.structures import Meshes
from pytorch3d.renderer import (
    OpenGLPerspectiveCameras, look_at_view_transform, look_at_rotation, 
    RasterizationSettings, MeshRenderer, MeshRasterizer, BlendParams,
    PointLights, SoftPhongShader, SoftSilhouetteShader, Textures, HardPhongShader,
)
# from pytorch3d.io import load_objs_as_meshes

class Renderer(torch.nn.Module):
    def __init__(self, image_size):
        super(Renderer, self).__init__()

        self.image_size = image_size
        # RENDERER
        MESH_COLOR = [0, 172, 223]
        # self.dog_obj = load_objs_as_meshes(['data/dog_B/dog_B/dog_B_tpose.obj'])
        self.mesh_color = torch.FloatTensor(MESH_COLOR)[None, None, :] / 255.0
        '''BlendParams 类用于控制渲染结果中不同像素之间的混合方式,以产生平滑的渲染效果。
        在这行代码中,BlendParams 是创建混合参数对象的构造函数,通过传递 sigma 和 gamma 参数来设置混合参数的值。sigma 控制了混合过程中的平滑程度。较大的 sigma 值将产生更加平滑的混合效果,而较小的 sigma 值则会产生更锐利的混合边缘。gamma 控制了混合过程中的权重调整。较大的 gamma 值将增加前景像素的权重,使其在混合中占据更大的比例,而较小的 gamma 值则会减小前景像素的权重,使其在混合中占据较小的比例。'''
        blend_params = BlendParams(sigma=1e-4, gamma=1e-4)

        raster_settings = RasterizationSettings(
            image_size=self.image_size, 
            blur_radius=np.log(1. / 1e-4 - 1.) * blend_params.sigma,
            faces_per_pixel=100,#细节更多,增加渲染时间
            # bin_size=None
        )

        R, T = look_at_view_transform(2.7, 0, 0) 
        self.cameras = OpenGLPerspectiveCameras(device=R.device, R=R, T=T)
        # lights = PointLights(device=R.device, location=[[0.0, 1.0, 0.0]])

        self.renderer = MeshRenderer(
            rasterizer=MeshRasterizer(
                cameras=self.cameras,
                raster_settings=raster_settings
            ),
            shader=SoftSilhouetteShader(
                blend_params=blend_params,
            )
        )

        lights = PointLights(location=[[0.0, 0.0, 3.0]])
        raster_settings_color = RasterizationSettings(
            image_size=self.image_size,
            blur_radius=0.0,
            faces_per_pixel=1,
        )

        self.color_renderer = MeshRenderer(
            rasterizer=MeshRasterizer(
                cameras=self.cameras,
                raster_settings=raster_settings_color
            ),
            shader=HardPhongShader(
                cameras=self.cameras,
                lights=lights,
            )
        )

    def forward(self, vertices, faces, render_texture=False):
        tex = torch.ones_like(vertices) * self.mesh_color # (1, V, 3)
        textures = Textures(verts_rgb=tex)
        mesh = Meshes(verts=vertices, faces=faces, textures=textures)
        # mesh = Meshes(verts=vertices, faces=faces, textures=self.dog_obj.textures)
        if render_texture:
            images = self.color_renderer(mesh)
        else:
            images = self.renderer(mesh)
        return images

三、pyrender渲染函数

3.1 关键代码

调用 PyTorch3D 的look_at_view_transform函数获取相机平移T,相机的投影函数选择透视相机函数PerspectiveCamera,垂直视场角(yfov)设置为 π / 3.0,即 60 度。这意味着相机的视锥体将在垂直方向上覆盖 60 度的视角范围。

R, T = look_at_view_transform(2.7, 0, 0)
camera_translation = T.numpy()
camera_pose = np.eye(4)
camera_pose[:3, 3] = camera_translation
camera = pyrender.PerspectiveCamera(yfov=np.pi / 3.0)

3.2 完整代码

代码会根据 Trimesh 创建一个 pyrender.Mesh 对象,并将其添加到 pyrender.Scene 中。代码还为场景添加了一个透视摄像机和三个定向灯。最后,使用 OffscreenRenderer 渲染场景,并将生成的彩色图像作为 PyTorch 张量返回。

import os
#https://pyrender.readthedocs.io/en/latest/examples/offscreen.html
# fix for windows from https://github.com/mmatl/pyrender/issues/117
# edit C:\Users\bjb10042\.conda\envs\bjb_env\Lib\site-packages\pyrender
# os.environ['PYOPENGL_PLATFORM'] = 'osmesa'
import torch
from torchvision.utils import make_grid
import numpy as np
import pyrender
import trimesh
from pytorch3d.renderer import look_at_view_transform

class Renderer:
    """
    Renderer used for visualizing the SMPL model
    Code adapted from https://github.com/vchoutas/smplify-x
    """
    def __init__(self, img_res=224):
        self.renderer = pyrender.OffscreenRenderer(viewport_width=img_res,
                                       viewport_height=img_res,
                                       point_size=1)
        self.focal_length = 5000
        self.camera_center = [img_res // 2, img_res // 2]

    def __call__(self, vertices, faces, camera_translation=None, focal_length=None):
        material = pyrender.MetallicRoughnessMaterial(
            metallicFactor=0.2,
            alphaMode='OPAQUE',
            baseColorFactor=(0.8, 0.3, 0.3, 1.0))

        R, T = look_at_view_transform(2.7, 0, 0)

        if np.all(camera_translation == None):
            # camera_translation = np.array([0.0, 0.0, 50.0])
            camera_translation = T.numpy()
        if np.all(focal_length != None):
            self.focal_length = focal_length[0]

        mesh = trimesh.Trimesh(vertices[0], faces[0], process=False)
        # rot = trimesh.transformations.rotation_matrix(
        #     np.radians(180), [1, 0, 0])
        # mesh.apply_transform(rot)
        mesh = pyrender.Mesh.from_trimesh(mesh, material=material)

        scene = pyrender.Scene(ambient_light=(0.5, 0.5, 0.5))
        scene.add(mesh, 'mesh')

        camera_pose = np.eye(4)
        camera_pose[:3, 3] = camera_translation
        # fx, fy, cx, cy = camera_matrix[0, 0], camera_matrix[1, 1], camera_matrix[0, 2], camera_matrix[1, 2]
        # fx = self.focal_length
        # fy = self.focal_length
        # cx = self.camera_center[0]
        # cy = self.camera_center[1]
        # camera = pyrender.IntrinsicsCamera(fx=fx, fy=fy, cx=cx, cy=cy, znear=1.0, zfar=100)
        camera = pyrender.PerspectiveCamera(yfov=np.pi / 3.0)
        scene.add(camera, pose=camera_pose)

        light = pyrender.DirectionalLight(color=[1.0, 1.0, 1.0], intensity=1)
        light_pose = np.eye(4)

        light_pose[:3, 3] = np.array([0, -1, 1])
        scene.add(light, pose=light_pose)

        light_pose[:3, 3] = np.array([0, 1, 1])
        scene.add(light, pose=light_pose)

        light_pose[:3, 3] = np.array([1, 1, 2])
        scene.add(light, pose=light_pose)

        color, rend_depth = self.renderer.render(scene, flags=pyrender.RenderFlags.RGBA)
        color = color.astype(np.float32) / 255.0
        return torch.from_numpy(color).float().unsqueeze(0)

省流:pyrender用PerspectiveCamera替换pytorch3d的OpenGLPerspectiveCameras,加上相机平移和相机垂直视角即可

目前看来,pyrender的PerspectiveCamera和pytorch3d的OpenGLPerspectiveCameras两个函数的默认相机配置非常类似。从pytorch3d的源码上看OpenGLPerspectiveCameras继承了FoVPerspectiveCameras函数,默认的fov设置为60。两者很容易替换。

##############################
def OpenGLPerspectiveCameras(
    znear: _BatchFloatType = 1.0,
    zfar: _BatchFloatType = 100.0,
    aspect_ratio: _BatchFloatType = 1.0,
    fov: _BatchFloatType = 60.0,##
    degrees: bool = True,
    R: torch.Tensor = _R,
    T: torch.Tensor = _T,
    device: Device = "cpu",
) -> "FoVPerspectiveCameras":

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

旅游项目day03

1. 前端整合后端发短信接口 2. 注册功能 后端提供注册接口,接受前端传入的参数,创建新的用户对象,保存到数据库。 接口设计: 实现步骤: 手机号码唯一性校验(后端一定要再次校验手机号唯一性&#xff09…

【图形学】颜色线性插值和Wu反走样算法

颜色线性插值 绘制一条颜色渐变的直线,直线上每一个点的颜色都来自端点颜色的线性插值。线性插值公式为 P ( 1 − t ) P s t a r t t P e n d P 是直线上任意一个点, P s t a r t 是直线的起点, P e n d 是直线的终点 对应直线上任意一点…

gin+gorm增删改查目录框架

从网上找资料,发现,很多都是直接的结构 路由,后端的controller层,还有model层,都是放在了同一个main.go文件中,如果写项目的话,还得自己去拆文件,拆代码,经过查询和自己总结,下面放…

计算机网络——数据链路层(1)

一、概述 在计算机网络中,数据链路层承担着点对点通信的任务,用于跨物理层在网段节点之间参数数据。它在网络分层中处于物理层之上,网路层之下。 在链路层的讨论中,我们将看到两种截然不同类型的链路层信道。第一种类型是广播信道…

数字身份所有权:Web3时代用户数据的掌控权

随着Web3时代的来临,数字身份的概念正焕发出崭新的光芒。在这个数字化的时代,用户的个人数据变得愈加珍贵,而Web3则为用户带来了数字身份所有权的概念,重新定义了用户与个人数据之间的关系。本文将深入探讨Web3时代用户数据的掌控…

【竞技宝】DOTA2:世一C遇到瓶颈? yatoro直言一号位上分太难了

北京时间2024年1月18日,spirit在去年再次拿到了TI国际邀请赛的冠军,成为了OG之后第二支两次在世界赛夺冠的战队,在夺冠之后,spirit直接给选手们放了假。此前AR夺冠的ESL吉隆坡站的比赛,spirit战队就并未参加&#xff0…

视频转码实例:把MP4转为MKV视频,一键批量转换的操作方法

在数字媒体时代,视频格式的多样性是不可避免的。经常把MP4格式的视频转换为MKV格式。MKV格式有较高的音频和视频质量,能在其他设备或软件上播放视频。以下是云炫AI智剪如何把MP4视频转为MKV格式的一键批量转换操作方法。 已转码的mkv视频效果缩略图展示…

kubernetes pod 高级

一、pod资源限制 1、什么是pod的资源限制 在Kubernetes集群中,为了使系统能够稳定的运行,通常会对Pod的资源使用量进行限制。 在Kubernetes集群中,如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话…

Git学习笔记(第4章):Git分支

目录 4.1 分支的概述 4.1.1 什么是分支 4.1.2 分支的好处 4.2 查看分支(查) 4.3 创建分支(增) 4.4 切换分支 4.5 修改分支(改) 4.6 合并分支(正常合并) 4.7 合并分支&#…

CGAL最小生成树、可视化

CGAL 5.4.5 - Surface Mesh: User Manual 1、Kruskal计算最小生成树 #include <CGAL/Simple_cartesian.h> #include <CGAL/Surface_mesh.h> #include <boost/graph/kruskal_min_spanning_tree.hpp> #include <iostream> #include <fstream> #inc…

贝塞尔曲线(Bezier Curve)原理、公式推导及matlab代码实现

目录 参考链接 定义 直观理解 公式推导 一次贝塞尔曲线&#xff08;线性公式&#xff09; 二次贝塞尔曲线&#xff08;二次方公式&#xff09; 三次贝塞尔曲线&#xff08;三次方公式&#xff09; n次贝塞尔曲线&#xff08;一般参数公式&#xff09; 代码实现 参考链接…

群晖NAS搭建WebDav结合内网穿透实现公网访问本地影视资源

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

2024华数杯国际数学建模B题思路+代码+模型+论文

2024华数杯国际数学建模B题思路代码模型论文&#xff1a;1.17上午第一时间更新&#xff0c;详细内容见文末名片 问题B&#xff1a;光伏电 背景 中国的电力构成包括传统的能源发电&#xff08;如煤炭、石油和天然气&#xff09;、可再生能源发电 &#xff08;如水力发电、风能…

OpenGL:关于纹理映射时任意四边形中的插值问题(二)

OpenGL&#xff1a;关于纹理映射时任意四边形中的插值问题-CSDN博客 上次是使用逆双线性插值的方法解决四边形纹理映射时产生的折痕问题。 其实也有点问题&#xff0c;就是双线性插值会使得纹理产生一点扭曲。 不是投影的效果。 想达到纹理投影的效果&#xff0c;可以使用透…

AndroidStudio下载安装教程

下载链接&#xff1a;官方下载 https://developer.android.google.cn/studio?hlzh-cn点击后弹出条款及条件页面&#xff0c;往下滑&#xff0c;勾选同意&#xff0c;然后就点击下载&#xff0c;等待下载完成 下载完成后双击打开&#xff0c;Next 继续Next 选择安装路径&am…

行列转化【附加面试题】

在MySQL中&#xff0c;行列转换是一种常见的操作。它包括行转列和列转行两种情况。 行转列&#xff1a;行转列是将表中的某些行转换成列&#xff0c;以提供更为清晰、易读的数据视图。例如&#xff0c;假设我们有一个包含科目和分数的表&#xff0c;我们可以使用SUM和CASE语句…

C++(13)——string

上篇文章中介绍了中部分函数的用法&#xff0c;本篇文章将继续对其他的函数进行介绍&#xff1a; 1. substr: string substr (size_t pos 0, size_t len npos) const; 函数的两个参数如上述代码所示&#xff0c;此函数的主要作用是根据一个已有的的对象的起始坐标开始&a…

基于python集成学习算法XGBoost农业数据可视化分析预测系统

文章目录 基于python集成学习算法XGBoost农业数据可视化分析预测系统一、项目简介二、开发环境三、项目技术四、功能结构五、功能实现模型构建封装类用于网格调参训练模型系统可视化数据请求接口模型评分 0.5*mse 六、系统实现七、总结 基于python集成学习算法XGBoost农业数据可…

我终于学会的前端技能——代码调试、打断点

在技术的世界里&#xff0c;要用魔法来打败魔法 说来惭愧我做前端已近三年了竟然还没有学会如何调试代码&#xff0c;也就是给自己的代码打上断点一步步看它的运行状态以达到理清代码运行逻辑、排查问题提升开发效率的目的。直到最近我才学会了这一技能&#xff0c;在这之前我…

JSP简单学习

jsp是在html中嵌入java代码 jsp也是在j2ee服务端中的java组件 第一次运行 在第一次运行jsp代码时会经历以下步骤&#xff0c;将jsp转为java代码&#xff0c;将java代码转为class文件。 所以通常会比较慢&#xff0c;编译后就好多了。 四大作用域 requestsessionpageapplica…