我在搅拌机中创建了一个简单的几何场景,在其中生成了一个立方体(在 pos (5,5,-2) 处),相机位于 (0,0,0) 处,面向 x 轴和 y 轴之间。 之后,我想用Python自己渲染场景。我成功了,但是图像中立方体的位置不一样。如下图所示。
我使用形状为 (3x3) 的 3x3 相机矩阵:
focal_length = 25 #blender has 50 (but with 50 the zoom is even stronger)
sensor_width = 20
sensor_height = 20
# Calculate the intrinsic matrix
fx = focal_length * width / sensor_width
fy = focal_length * height / sensor_height
cx = width / 2 # principal point is our image center
cy = height / 2
camera_matrix = np.array([
[fx, 0, cx],
[0, fy, cy],
[0, 0, 1]], np.float32)
形状为 (3x3) 的旋转矩阵:
angle_x = 90
angle_y = 0
angle_z = 45
rotation_matrix_x = np.array(
[
[1, 0, 0],
[0, np.cos(angle_x), -np.sin(angle_x)],
[0, np.sin(angle_x), np.cos(angle_x)],
]
)
rotation_matrix_y = np.array(
[
[np.cos(angle_y), 0, np.sin(angle_y)],
[0, 1, 0],
[-np.sin(angle_y), 0, np.cos(angle_y)],
]
)
rotation_matrix_z = np.array(
[
[np.cos(angle_z), -np.sin(angle_z), 0],
[np.sin(angle_z), np.cos(angle_z), 0],
[0, 0, 1],
]
)
rotation_matrix = rotation_matrix_x @ rotation_matrix_y @ rotation_matrix_z
和平移矩阵 (3x1):
translation_matrix = np.array([[0], [0], [0]])
然后我定义我的投影矩阵,如下所示:
projection_matrix = camera_matrix @ np.hstack((rotation_matrix, translation_matrix))
我还添加了最后一行来获得形状(4x4):
new_row = np.array([[0, 0, 0, 1]], dtype=np.float32)
projection_matrix = np.vstack((projection_matrix, new_row)
我创建了一个 3D 立方体(通过定义 8 个点): 创建了立方体 [(4.5, 4.5, -1.5), (4.5, 5.5, -1.5), (5.5, 5.5, -1.5), (5.5, 4.5, -1.5), (4.5, 4.5, -0.5), ( 4.5, 5.5, -0.5), (5.5, 5.5, -0.5), (5.5, 4.5, -0.5)] 中心:(5, 5, -1) 并将每个 3D 点转换为 2D 点:
def project_3d_to_2d(x, y, z, projection_matrix):
point_3d = np.array([x,y,z,1])
point_after_matrix = projection_matrix@point_3d
#Normalization of the projected point
point_after_matrix /= point_after_matrix[2] #z coordinate
points_2d = point_after_matrix[:2]
return points_2d
生成的立方体与搅拌机生成的立方体不匹配。我从 Blender 获取了相机矩阵,但它的形状不同(4x4),我无法使用这个(我也得到了他们的投影矩阵,但应用后我什至看不到我的立方体)。
我的大问题是: 我可以将搅拌机相机设置为与我自己使用的相机矩阵完全匹配吗? 或者我可以将搅拌机相机设置转换为我的相机矩阵吗?
非常感谢你们:)
好吧,看来我找到了解决方案。 这是一个典型的菜鸟错误。我在 Blender 中创建的立方体比我自己脚本中的立方体小 :D。调整后...就可以了。