目录
渲染在右下角
渲染立方体到指定位置 还没成功
渲染在右下角
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_centeru1, v1 = target_pt1u2, v2 = target_pt2# 图像中心点c_x = img_width / 2c_y = img_height / 2# 初始深度约束 dtarget_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_zfor i in range(max_iter):# 计算当前 t_zt_z = Cz - d# 计算当前投影比例scale_x = (u2 - u1) / (obj_width * f_x / d)scale_y = (v2 - v1) / (obj_height * f_y / d)# 更新深度约束 dd_new_x = (obj_width * f_x) / (u2 - u1) * scale_xd_new_y = (obj_height * f_y) / (v2 - v1) * scale_yd_new = max(abs(d_new_x), abs(d_new_y))# 检查收敛if abs(d_new - d) < tol:breakd = d_new# 最终 t_zt_z = Cz - d# 计算 t_x 和 t_ytarget_x = (u1 + u2) / 2 # 目标区域中心点 u 坐标target_y = (v1 + v2) / 2 # 目标区域中心点 v 坐标t_x = Cx - (target_x - c_x) * t_z / f_xt_y = Cy - (target_y - c_y) * t_z / f_yreturn t_x, t_y, -t_zdef 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)# 设置相机内参矩阵 KK = 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)