# -*- coding: utf-8 -*-
'''
CSDN博客:https://blog.csdn.net/suiyingy
乐乐感知学堂公众号
长期分享三维、二维感知、大模型等AI算法和demo以及金融量化分析算法等。
本程序作用:根据相机朝向向量获取投影矩阵,以左视图为例。
专栏地址:https://blog.csdn.net/suiyingy/category_12462636.html
'''
import os
import cv2
import trimesh
import numpy as np
import open3d as o3d
from pathlib import Path
from pyrender import Mesh, Scene, OffscreenRenderer, IntrinsicsCamera, Viewer
# 根据向量获取旋转矩阵
# n1为目标z轴方向,左视图对应为[-1, 0, 0]
# theta为绕z轴逆时针旋转角度,单位为弧度
# 左视图绕z轴顺时针旋转90°,即theta为-np.pi/2
def get_vector_r(n1, theta):
# 默认z轴方向
n0 = np.array([0, 0, 1])
# 计算旋转角度
the = np.arccos(np.dot(n0, n1) / np.linalg.norm(n0) / np.linalg.norm(n1))
# 根据向量叉乘计算旋转轴
r_axis = np.cross(n0, n1)
# open3d中旋转向量的模长表示旋转角度
r_axis = r_axis / np.linalg.norm(r_axis) * the
# 计算旋转矩阵
pcd = o3d.geometry.PointCloud()
R = pcd.get_rotation_matrix_from_axis_angle(r_axis.T)
pcd.rotate(R)
print('the: ', the)
print('R1: ', R)
# 绕z轴再次旋转
rz = pcd.get_rotation_matrix_from_xyz((0, 0, theta))
R = R.dot(rz)
print('R2: ', R)
# [[0.0, 0.0, -1.0],
# [-1.0, 0.0, 0.0],
# [0.0, 1.0, 0.0]]
return R
# ratio,目标最长边占视野的比例,上述计算可让模型填充整个视野
# 设置比例为了使视野范围更大一些,留有一些空白
# 相机放置越远,则视野范围越大
def get_rt_array(mesh, ratio=0.7):
v = mesh.vertices
f = mesh.faces
#这样得到的v和f格式是trimesh内置的格式,不能直接用于其它计算,需要转换为numpy
v = np.array(v)
f = np.array(f)
# 计算点云在x,y,z三个方向上的长度
# 除以ratio是为了对长度进行放大,并作为图像视野大小,从而使得模型在图片中的比例约为ratio
d = (np.max(v, axis=0) - np.min(v, axis=0)) / ratio
d = np.round(d)
# w : W = fx : D, 假设h=f, 那么D=W,D表示相机距模型的距离
# h : H = fy : D, 假设h=f, 那么D=H,D表示相机距模型的距离
# 设置相机位置为 (-max(d[1], d[2]), 0.0, 0.0)
T = np.array([[-max(d[1], d[2]), 0.0, 0.0]]).T
pcd = o3d.geometry.PointCloud()
# 左视图,根据向量获取R矩阵
R = get_vector_r(np.array([-1, 0, 0]), -np.pi / 2)
print('R: ', R)
RT = np.hstack((R, T))
RT = np.vstack((RT, [0, 0, 0, 1]))
return RT
def get_project_image(mesh, RT, save_name='result', save_dir=r'images'):
save_dir = str(Path(save_dir)) + '/'
os.makedirs(save_dir, exist_ok=True)
# 成像后图片的高度和宽度像素大小
w, h = 800, 600
# 相机焦距
fx, fy = 800, 600
# 假设模型在宽度和高度方向上的实际尺寸为W和H
# D表示相机距模型的距离
# w : W = fx : D, 假设w=fx, 那么D=W,
# h : H = fy : D, 假设h=fy, 那么D=H
# 也就是说相机放置距离与视野范围相等,即可看全整个视野
# 显示三维模型,默认x轴向右、y轴向上、z轴向外
# mesh.show(background=[1,0,0,1])
# 构建渲染场景
scene_mesh = Mesh.from_trimesh(mesh)
scene = Scene(ambient_light=np.array([1.0, 1.0, 1.0, 1.0]), bg_color=[1,0,0,1])
scene.add(scene_mesh)
# 相机位姿矩阵
camera_pose = RT
# 相机内参
camera_intrinsics = IntrinsicsCamera(
fx=fx, fy=fy, cx=w/2, cy=h/2 # 适应您的视口大小
)
#向场景中添加相机
scene.add(camera_intrinsics, pose=camera_pose)
# 可视化场景
# Viewer(scene)
# 保存投影图片
renderer = OffscreenRenderer(w, h)
color_image, _ = renderer.render(scene)
cv2.imwrite(save_dir + save_name + '.png', color_image[:, :, ::-1])
cv2.namedWindow('topview', 0)
cv2.imshow('topview', color_image[:, :, ::-1])
cv2.waitKey(0)
if __name__ == '__main__':
mesh = trimesh.load('model.obj', force='mesh')
# 原始模型可视化
# mesh.show()
# 获取左视图相机的RT位姿矩阵
RT = get_rt_array(mesh, ratio=0.7)
print('RT: ', RT)
# 根据RT矩阵进行投影
get_project_image(mesh, RT, save_name='leftview-vector-0.7', save_dir=r'images')
Coding的叶子
- 粉丝: 5w+
- 资源: 45
最新资源
- 基于WebRTC技术的实时通信与视频会议系统设计
- 基于WebRTC的多参与者视频会议系统中simulcast技术的研究与评估
- 拍打经络操mmexport1735392775826.mp4
- 破损图像修复开题报告&&任务书
- 基于运动感知的WebRTC多点视频会议自适应层选择研究
- 八部金刚功mmexport1735392770600.mp4
- 车用驱动电机原理与控制基础-P141公式(6-22)
- SINAMICS S120变频器调试指南及关键步骤解析
- WebRTC应用程序中的质量体验评估与关键性能指标分析
- Group Assignment-Amazon-and-Alipay-r1.pptx
- 级联pwm整流器(级联H桥CHB)(单相交流220V-直流135*3整流)仿真,动稳态性能良好,0.5s切不平衡负载,0.6s启动直流电压均衡控制,附带仿真介绍文档,详细讲述仿真搭建过程,并附带参考文
- 基于WebRTC应用的视频质量客观评估技术-VMAF模型研究与实证分析
- 定位助手_202412131.apk
- 基于Spring Boot的社区团购系统全解析
- 新能源6.6KW7KW 3.3KW 11KW车载充电机OBC开关电源设计方案 另有15KW ai默生 数字控制:电压电流环控制核心算法 PFC?LLC采用TMS320F28035芯片 3.3KW车载充
- 汇川H5U走EtherCat控制伺服带HMI程序,轴控制和气缸控制有做功能块,通俗易懂,是学习汇川总线的好帮手
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈