自动计算相机pose,pyrender渲染例子
- IT业界
- 2025-09-14 09:12:01

目录
渲染在右下角
渲染立方体到指定位置 还没成功
渲染在右下角 import cv2 import numpy as np import pyrender import trimesh def compute_camera_translation(vertices_center, obj_width, obj_height, target_pt1, target_pt2, f_x, f_y, img_width, img_height, max_iter=10, tol=1e-6): """ 计算相机平移参数,使模型包围盒的两个角点投影到目标像素点 Args: vertices_center: 模型中心坐标 [Cx, Cy, Cz] obj_width: 包围盒宽度 (米) obj_height: 包围盒高度 (米) target_pt1: 目标点1 [u1, v1] (像素) target_pt2: 目标点2 [u2, v2] (像素) f_x: 相机x轴焦距 f_y: 相机y轴焦距 img_width: 图像宽度 (像素) img_height: 图像高度 (像素) max_iter: 最大迭代次数 tol: 收敛阈值 Returns: t_x, t_y, t_z: 相机平移参数 """ Cx, Cy, Cz = vertices_center u1, v1 = target_pt1 u2, v2 = target_pt2 # 图像中心点 c_x = img_width / 2 c_y = img_height / 2 # 初始深度约束 d target_width = abs(u2 - u1) # 目标区域的宽度(像素) target_height = abs(v2 - v1) # 目标区域的高度(像素) d_x = (obj_width * f_x) / target_width # 水平方向的深度约束 d_y = (obj_height * f_y) / target_height # 垂直方向的深度约束 d = max(abs(d_x), abs(d_y)) # 初始深度约束 # 迭代优化 t_z for i in range(max_iter): # 计算当前 t_z t_z = Cz - d # 计算当前投影比例 scale_x = (u2 - u1) / (obj_width * f_x / d) scale_y = (v2 - v1) / (obj_height * f_y / d) # 更新深度约束 d d_new_x = (obj_width * f_x) / (u2 - u1) * scale_x d_new_y = (obj_height * f_y) / (v2 - v1) * scale_y d_new = max(abs(d_new_x), abs(d_new_y)) # 检查收敛 if abs(d_new - d) < tol: break d = d_new # 最终 t_z t_z = Cz - d # 计算 t_x 和 t_y target_x = (u1 + u2) / 2 # 目标区域中心点 u 坐标 target_y = (v1 + v2) / 2 # 目标区域中心点 v 坐标 t_x = Cx - (target_x - c_x) * t_z / f_x t_y = Cy - (target_y - c_y) * t_z / f_y return t_x, t_y, -t_z def render_smpl_with_camera(vertices, faces, t_x, t_y, t_z, f_x, f_y, img_width, img_height): """ 使用 pyrender 渲染 SMPL 模型,并验证相机参数是否正确 Args: vertices: SMPL 模型的顶点坐标 (N, 3) faces: SMPL 模型的面信息 (M, 3) t_x, t_y, t_z: 相机平移参数 f_x, f_y: 相机焦距 img_width: 图像宽度 img_height: 图像高度 """ # 创建场景 scene = pyrender.Scene() # 添加 SMPL 模型 mesh = trimesh.Trimesh(vertices=vertices, faces=faces) mesh = pyrender.Mesh.from_trimesh(mesh) scene.add(mesh) # 设置相机内参矩阵 K K = np.array([ [f_x, 0, img_width / 2], [0, f_y, img_height / 2], [0, 0, 1] ]) # 创建相机 camera = pyrender.IntrinsicsCamera(fx=f_x, fy=f_y, cx=img_width / 2, cy=img_height / 2) camera_pose = np.eye(4) camera_pose[:3, 3] = [t_x, t_y, t_z] # 设置相机平移 scene.add(camera, pose=camera_pose) # 创建渲染器 renderer = pyrender.OffscreenRenderer(img_width, img_height) # 渲染图像 color, depth = renderer.render(scene) cv2.imshow('SMPL', color) cv2.waitKey(0) # 输入参数 vertices_center = [0.06476647, 0.6240687, 0.05080975] obj_width = 0.5485740602016449 obj_height = 1.8117486238479614 target_pt1 = [287, 156] target_pt2 = [594, 1260] img_width = 720 img_height = 1280 # 计算焦距 fov_deg = 50 fov_rad = np.radians(fov_deg) aspect_ratio = img_width / img_height f_y = (img_height / 2) / np.tan(fov_rad / 2) f_x = f_y * aspect_ratio # 计算平移参数 t_x, t_y, t_z = compute_camera_translation(vertices_center, obj_width, obj_height, target_pt1, target_pt2, f_x, f_y, img_width, img_height) print(f"相机平移参数:") print(f"t_x = {t_x:.4f}m") print(f"t_y = {t_y:.4f}m") print(f"t_z = {t_z:.4f}m") # 加载 SMPL 模型(假设 vertices 和 faces 已加载) # vertices: (N, 3) 顶点坐标 # faces: (M, 3) 面信息 # 这里用一个简单的立方体作为示例 vertices = np.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1] ]) faces = np.array([ [0, 1, 2], [2, 3, 0], [4, 5, 6], [6, 7, 4], [0, 1, 5], [5, 4, 0], [1, 2, 6], [6, 5, 1], [2, 3, 7], [7, 6, 2], [3, 0, 4], [4, 7, 3] ]) # 渲染并验证 render_smpl_with_camera(vertices, faces, t_x, t_y, t_z, f_x, f_y, img_width, img_height) 渲染立方体到指定位置 还没成功 import cv2 import numpy as np import pyrender import trimesh # 定义立方体顶点和面 vertices = np.array([ [0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0], [0, 0, 1], [1, 0, 1], [1, 1, 1], [0, 1, 1] ], dtype=np.float32) faces = np.array([ [0, 1, 2], [2, 3, 0], [4, 5, 6], [6, 7, 4], [0, 1, 5], [5, 4, 0], [1, 2, 6], [6, 5, 1], [2, 3, 7], [7, 6, 2], [3, 0, 4], [4, 7, 3] ]) # 渲染参数 img_width = 800 img_height = 800 target_x, target_y = 100, 100 # 目标区域左上角 target_w, target_h = 400, 400 # 目标区域大小 # ==================== 关键计算步骤 ==================== # 1. 计算焦距(基于垂直 FOV=55°) fov_deg = 55 fov_rad = np.radians(fov_deg) f = (img_height / 2) / np.tan(fov_rad / 2) # 焦距 f ≈ 1280/(2*tan(27.5°)) ≈ 1280/0.52 ≈ 2461.5 # 2. 计算立方体需要移动到的位置(使投影到目标区域) # 目标区域的中心坐标(图像坐标系) center_u = target_x + target_w / 2 # 300 center_v = target_y + target_h / 2 # 300 # 将图像坐标系中心点转换到相机坐标系(归一化坐标) norm_x = (center_u - img_width/2) / f # (300-640)/2461.5 ≈ -0.138 norm_y = (center_v - img_height/2) / f # (300-640)/2461.5 ≈ -0.138 # 3. 确定立方体在相机空间的深度 Z(确保立方体大小匹配目标区域) # 假设立方体边长为 1,投影到 400 像素宽度需要满足:1/Z * f = 400 → Z = f / 400 ≈ 6.15 Z = f * (1.0 / target_w) # 根据目标像素宽度调整深度 print(f"立方体深度 Z = {Z:.2f}") # 4. 计算立方体的平移量(使中心点投影到目标区域中心) # 立方体原始中心为 (0.5, 0.5, 0.5),需要移动到 (X, Y, Z) X = norm_x * Z + 0.5 # X ≈ (-0.138)*6.15 + 0.5 ≈ -0.85 + 0.5 = -0.35 Y = norm_y * Z + 0.5 # Y ≈ -0.35 translation = np.array([X, Y, -Z - 0.5]) # 移动立方体中心到 (X, Y, Z) # 平移立方体顶点 translated_vertices = vertices + translation # ==================== PyRender 渲染代码 ==================== # 创建场景 scene = pyrender.Scene() # 添加平移后的立方体 mesh = pyrender.Mesh.from_trimesh(trimesh.Trimesh(vertices=translated_vertices, faces=faces)) scene.add(mesh) # 设置相机(位置在原点,看向 -Z 方向) camera = pyrender.PerspectiveCamera( yfov=fov_rad, aspectRatio=img_width/img_height, znear=0.1, zfar=100 ) camera_pose = np.eye(4) # 相机位于原点 (0,0,0) scene.add(camera, pose=camera_pose) # 添加光源(避免渲染全黑) light = pyrender.DirectionalLight(color=[1.0, 1.0, 1.0], intensity=5.0) scene.add(light, pose=np.eye(4)) # 渲染图像 renderer = pyrender.OffscreenRenderer(img_width, img_height) color, depth = renderer.render(scene) # 裁剪目标区域并显示 # result = color[target_y:target_y+target_h, target_x:target_x+target_w] result = color cv2.imshow("Rendered Cube", result) cv2.waitKey(0)
自动计算相机pose,pyrender渲染例子由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“自动计算相机pose,pyrender渲染例子”
 
               
               
               
               
               
               
               
               
   
   
   
   
   
   
   
   
   
   
   
  