自动计算相机pose,pyrender渲染例子

embedded/2025/3/4 7:28:57/

目录

渲染在右下角

渲染立方体到指定位置 还没成功


渲染在右下角

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)


http://www.ppmy.cn/embedded/169844.html

相关文章

linux插入模块和删除模块

一、基础知识 模块时一种向Linux内核添加设备驱动、文件系统及其他组件的有效方法&#xff0c;不需要重新编译内核或者重启系统。 内核模块具有以下优点&#xff1a; 1.通过使用模块&#xff0c;内核发布者能够预先编译大量驱动程序&#xff0c;而不会使内核映像的尺寸放生膨胀…

Python网络爬虫技术详解文档

Python网络爬虫技术详解文档 目录 网络爬虫概述爬虫核心技术解析常用Python爬虫库实战案例演示反爬虫机制与应对策略爬虫法律与道德规范高级爬虫技术资源推荐与学习路径1. 网络爬虫概述 1.1 什么是网络爬虫 网络爬虫(Web Crawler)是一种按特定规则自动抓取互联网信息的程序…

【计算机网络入门】初学计算机网络(七)

目录 1. 滑动窗口机制 2. 停止等待协议&#xff08;S-W&#xff09; 2.1 滑动窗口机制 2.2 确认机制 2.3 重传机制 2.4 为什么要给帧编号 3. 后退N帧协议&#xff08;GBN&#xff09; 3.1 滑动窗口机制 3.2 确认机制 3.3 重传机制 4. 选择重传协议&#xff08;SR&a…

W3C标准和ES规范之一文通

W3C标准和ES规范之一文通 以下是关于W3C标准和ES规范的透彻解析&#xff0c;通过结构化对比和生活化类比帮助理解和记忆&#xff1a; 一、核心概念对比&#xff08;总览&#xff09; 维度W3C标准ES规范&#xff08;ECMAScript&#xff09;定位Web技术的建筑蓝图JavaScript的语…

计算机网络-面试总结

计算机网络 从输入一个URL到页面加载完成的过程 整体流程 DNS查询过程SSL四次握手HTTP 的长连接与短连接 HTTP 的 GET 和 POST 区别浏览器访问资源没有响应&#xff0c;怎么排查? OSI七层参考模型 TCP/IP四层参考模型比较 TCP/IP 参考模型与 OSI 参考模型 TCP三次握手&四…

使用haproxy实现MySQL服务器负载均衡

一、环境准备 主机名IP地址备注openEuler-1192.168.121.11mysql-server-1openEuler-2192.168.121.12mysql-server-2openEuler-3192.168.121.13clientRocky-1192.168.121.51haproxy 二、mysql-server配置 [rootopenEuler-1 ~]# yum install -y mariadb-server [rootopenEuler…

【错误记录】Windows 中 DevEco Studio 真机调试无法连接设备 ( 低版本的 HarmonyOS 4.2.0 华为手机无法在 DevEco Studio 5.0.2 上真机调试 )

文章目录 一、错误记录二、问题排查三、解决方案 参考文档 : hdc&#xff08;HarmonyOS Device Connector&#xff09;文档设备连接后&#xff0c;无法识别设备的处理指导真机调试流程 一、错误记录 手机 使用的是 HarmonyOS 4.2.0 系统 ; 使用 HarmonyOS 的 hdc 工具 , 执行 …

postgresql链接详解

PostgreSQL连接概述 连接基础 在探讨PostgreSQL连接的基础之前&#xff0c;我们需要理解什么是数据库连接。 数据库连接 是客户端应用程序与数据库服务器之间建立的一种通信通道&#xff0c;使用户能够访问和操作数据库中的数据。 PostgreSQL连接涉及以下几个关键要素&#…