Skip to content

几何变换

Open3D 的几何类型提供了多种变换方法。本教程展示如何使用 translate、rotate、scale 和 transform。

我们首先来看的变换方法是 translate。该方法接受一个三维向量 tt 作为输入,并将几何体的所有点/顶点按该向量平移,即 vt=v+tv_t = v + t。下面的代码展示了如何把网格分别沿 x 方向和 y 方向各平移一次。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_tx = copy.deepcopy(mesh).translate((1.3, 0, 0))
mesh_ty = copy.deepcopy(mesh).translate((0, 1.3, 0))
print(f'Center of mesh: {mesh.get_center()}')
print(f'Center of mesh tx: {mesh_tx.get_center()}')
print(f'Center of mesh ty: {mesh_ty.get_center()}')
o3d.visualization.draw_geometries([mesh, mesh_tx, mesh_ty])

tutorial_geometry_transformation_3_1.png

输出:

Center of mesh: [0.05167549 0.05167549 0.05167549]
Center of mesh tx: [1.35167549 0.05167549 0.05167549]
Center of mesh ty: [0.05167549 1.35167549 0.05167549]

该方法还有第二个参数 relative,默认值为 True。如果设为 False,则几何体的中心会被直接平移到第一个参数所指定的位置。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_mv = copy.deepcopy(mesh).translate((2, 2, 2), relative=False)
print(f'Center of mesh: {mesh.get_center()}')
print(f'Center of translated mesh: {mesh_mv.get_center()}')
o3d.visualization.draw_geometries([mesh, mesh_mv])

tutorial_geometry_transformation_6_1.png

输出:

Center of mesh: [0.05167549 0.05167549 0.05167549]
Center of translated mesh: [2. 2. 2.]

Open3D 的几何类型还可以用 rotate 方法进行旋转。它以旋转矩阵 RR 作为第一个参数。由于三维旋转可以用多种方式参数化,Open3D 提供了便捷函数,用于把不同的参数化形式转换为旋转矩阵:

  • 用 get_rotation_matrix_from_xyz 从欧拉角(Euler angles)转换(其中 xyz 也可以是 yzx、zxy、xzy、zyx、yxz 等形式)
  • 用 get_rotation_matrix_from_axis_angle 从轴-角(Axis-angle)表示转换
  • 用 get_rotation_matrix_from_quaternion 从四元数(Quaternions)转换

下面的代码使用欧拉角来旋转网格。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_r = copy.deepcopy(mesh)
R = mesh.get_rotation_matrix_from_xyz((np.pi / 2, 0, np.pi / 4))
mesh_r.rotate(R, center=(0, 0, 0))
o3d.visualization.draw_geometries([mesh, mesh_r])

tutorial_geometry_transformation_8_1.png

rotate 函数有第二个参数 center,默认值为 True。这表示物体在施加旋转之前会先被移到中心,旋转之后再移回原来的中心位置。如果将该参数设为 False,则旋转会直接施加,即整个几何体绕坐标中心旋转。这意味着旋转后网格的中心位置可能会发生变化。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_r = copy.deepcopy(mesh).translate((2, 0, 0))
mesh_r.rotate(mesh.get_rotation_matrix_from_xyz((np.pi / 2, 0, np.pi / 4)),
center=(0, 0, 0))
o3d.visualization.draw_geometries([mesh, mesh_r])

tutorial_geometry_transformation_10_1.png

Open3D 几何类型的顶点和点也可以用 scale 进行缩放,vs=s⋅vv_s = s \cdot v。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_s = copy.deepcopy(mesh).translate((2, 0, 0))
mesh_s.scale(0.5, center=mesh_s.get_center())
o3d.visualization.draw_geometries([mesh, mesh_s])

tutorial_geometry_transformation_12_1.png

scale 方法同样有第二个参数 center,默认值为 True。如果设为 False,则物体在缩放前不会被移到中心,因此缩放操作可能会改变物体的中心位置。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
mesh_s = copy.deepcopy(mesh).translate((2, 1, 0))
mesh_s.scale(0.5, center=(0, 0, 0))
o3d.visualization.draw_geometries([mesh, mesh_s])

tutorial_geometry_transformation_14_1.png

Open3D 还支持用 transform 方法施加由 4×44\times4 齐次变换矩阵(homogeneous transformation matrix)定义的一般变换。

mesh = o3d.geometry.TriangleMesh.create_coordinate_frame()
T = np.eye(4)
T[:3, :3] = mesh.get_rotation_matrix_from_xyz((0, np.pi / 3, np.pi / 2))
T[0, 3] = 1
T[1, 3] = 1.3
print(T)
mesh_t = copy.deepcopy(mesh).transform(T)
o3d.visualization.draw_geometries([mesh, mesh_t])

tutorial_geometry_transformation_16_1.png

输出:

[[ 3.06161700e-17 -5.00000000e-01 8.66025404e-01 1.00000000e+00]
[ 1.00000000e+00 6.12323400e-17 0.00000000e+00 1.30000000e+00]
[-5.30287619e-17 8.66025404e-01 5.00000000e-01 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 1.00000000e+00]]