You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blender相机参数适配OpenCV:3D点转2D图像投影失败排查

解决Blender到OpenCV的3D点投影匹配问题

你的问题核心是Blender与OpenCV的坐标系、旋转定义不匹配,直接复用Blender的旋转参数必然会出错,以下是具体修正方案:

1. 坐标系差异说明

Blender和OpenCV的轴定义完全不同:

  • Blender:右手系,世界坐标系X向右、Y向上、Z向前;相机朝向本地**-Z**方向(视图沿-Z轴观察)
  • OpenCV:右手系,相机坐标系X向右、Y向下、Z向前(视图沿+Z轴观察);图像坐标系Y轴向下

第一步要把Blender的世界坐标转换为OpenCV兼容的坐标:

# Blender坐标(X,Y,Z) → OpenCV坐标(X, -Z, Y)
def blender_to_cv(blender_point):
    x, y, z = blender_point
    return (x, -z, y)

2. 正确转换相机旋转参数

Blender的欧拉角是物体自身坐标系的旋转顺序(默认XYZ),而OpenCV的projectPoints的rvec是世界到相机坐标系的旋转向量,不能直接把欧拉角reshape成向量,必须经过坐标系转换:

步骤1:构建Blender的旋转矩阵

以你设置的旋转参数(X=90°, Y=0°, Z=-45°)为例,先按XYZ顺序生成旋转矩阵:

import numpy as np
import cv2

blender_rot_deg = (90, 0, -45)
blender_rot_rad = np.radians(blender_rot_deg)

# 绕X轴旋转矩阵
rx = np.array([
    [1, 0, 0],
    [0, np.cos(blender_rot_rad[0]), -np.sin(blender_rot_rad[0])],
    [0, np.sin(blender_rot_rad[0]), np.cos(blender_rot_rad[0])]
])
# 绕Y轴旋转矩阵
ry = np.array([
    [np.cos(blender_rot_rad[1]), 0, np.sin(blender_rot_rad[1])],
    [0, 1, 0],
    [-np.sin(blender_rot_rad[1]), 0, np.cos(blender_rot_rad[1])]
])
# 绕Z轴旋转矩阵
rz = np.array([
    [np.cos(blender_rot_rad[2]), -np.sin(blender_rot_rad[2]), 0],
    [np.sin(blender_rot_rad[2]), np.cos(blender_rot_rad[2]), 0],
    [0, 0, 1]
])

# Blender旋转矩阵:先X→再Y→再Z(物体自身轴旋转顺序)
blender_rot_mat = rz @ ry @ rx

步骤2:转换为OpenCV兼容的旋转矩阵

需要修正坐标系的轴方向(适配OpenCV的相机朝向和Y轴方向):

# 坐标系转换矩阵:翻转Blender的Y轴和Z轴,适配OpenCV定义
cv_coord_transform = np.array([
    [1, 0, 0],
    [0, 0, -1],
    [0, 1, 0]
])
# 生成OpenCV的旋转矩阵
cv_rot_mat = cv_coord_transform @ blender_rot_mat

# 转换为旋转向量rvec
rvec, _ = cv2.Rodrigues(cv_rot_mat)

3. 匹配相机焦距参数

你的相机矩阵主点设置cx=width/2, cy=height/2是对的,但需要确保焦距fx/fy和Blender的相机FOV匹配。比如Blender默认FOV为60°,按以下方式计算:

width = 640
height = 480
fov_deg = 60
fov_rad = np.radians(fov_deg)

fx = width / (2 * np.tan(fov_rad / 2))
fy = height / (2 * np.tan(fov_rad / 2))
cx = width / 2
cy = height / 2

camera_matrix = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]], dtype=np.float32)

4. 投影3D点

把Blender中的立方体顶点转换为OpenCV坐标后,执行投影:

# Blender中立方体的8个顶点(中心在(5,5,0),边长1)
blender_cube_verts = [
    (4.5,4.5,-0.5), (5.5,4.5,-0.5), (5.5,5.5,-0.5), (4.5,5.5,-0.5),
    (4.5,4.5,0.5), (5.5,4.5,0.5), (5.5,5.5,0.5), (4.5,5.5,0.5)
]
# 转换为OpenCV坐标
cv_cube_verts = np.array([blender_to_cv(v) for v in blender_cube_verts], dtype=np.float32)

# 相机在世界原点,平移向量tvec为0
tvec = np.zeros((3,1), dtype=np.float32)
# 无畸变参数
dist_coeffs = np.zeros((4,1), dtype=np.float32)

# 执行投影
img_pts, _ = cv2.projectPoints(cv_cube_verts, rvec, tvec, camera_matrix, dist_coeffs)

关键注意事项

  • 确认Blender的欧拉角旋转顺序:在Blender物体属性→旋转→顺序中查看,默认是XYZ,如果是其他顺序(如ZXY),需要调整旋转矩阵的乘法顺序
  • 相机朝向差异:Blender相机看向-Z,OpenCV看向+Z,这是旋转转换中必须处理的核心点

内容的提问来源于stack exchange,提问作者Yannik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:32:08