文章目录
- 点云特征
- 几何变换
- 点云框线
点云特征
【PointCloud】是open3d中用于点云处理的类,封装了包括几何变换、数据滤波、聚类分割等一系列实用算法,本例中所有例程均基于官方提供的pcd格式数据
# 此行代码后面不再重复引入
import open3d as o3d
pcdDemo = o3d.data.PCDPointCloud()
pcd = o3d.io.read_point_cloud(pcdDemo.path)
# 网速不好,可以下载之后在本地读取
# pcd = o3d.io.read_point_cloud("fragment.pcd")
点云类中封装了一些方法,用以提取点云的特征,调用pcd中的这些方法,其返回值如下
pcd.dimension() #3 点云维度为3
pcd.has_colors() # True 点云有颜色
pcd.has_covariances() # False 对象中不含协方差矩阵
pcd.has_normals() # True 含法向量
pcd.has_points() # True 点云中有点
pcd.is_empty() # False 点云不为空
pcd.get_geometry_type() # 几何体的类型是点云
通过下面三个函数,可以获取点云对象三个坐标的最大值、最小值以及质心。
pcd.get_max_bound() # [3.51953125, 2.76171875, 1.53042805]
pcd.get_min_bound() # [1.15198874, 0.81527287, 0.72640908]
pcd.get_center() # [2.27219892, 1.73894217, 1.31530002]
对于点云中的某点,其协方差矩阵为
- 【estimate_covariances】方法可以计算每个点的协方差矩阵。
- 【compute_mean_and_covariance】可计算整个点云及其协方差的均值。
M_and_C = pcd.compute_mean_and_covariance()
点云类为单点提供了两种距离属性,分别是最邻近距离和Mahalanobis距离,对应的函数分别是 【compute_nearest_neighbor_distance】和 【compute_mahalanobis_distance】。
最邻近距离即当前点和离它最近的其他点的距离;Mahalanobis距离的定义则为
其中为该点对应的协方差矩阵。
几何变换
点云类提供了平移、缩放以及旋转的空间变换方法,可以实现如下转换。
上图中,从左向右、从上向下从0开始计序,6个点云分别向左和向右进行了平移,其中0号点云是原图;第2号青色的点云进行了缩放;第二排的三个点云则进行了不同程度的旋转。作图函数如下,考虑到点云图床中以左下角为坐标原点,轴向上,轴向右,所以图像在保存时手动进行了翻转。
from copy import deepcopy
pcds = []
for i in range(6):
x, y = i%3, i//3
p = deepcopy(pcd).translate((2.5*x, 2.5*y, 0))
pcds.append(p)
colors = [(1,0,0), (0,1,1), (0,1,0), (0,0,1), (1,0,1)]
for i,c in enumerate(colors, 1):
pcds[i].paint_uniform_color(c)
# 2号点云,演示缩放
pcds[2].scale(0.5, center=pcds[2].get_center())
# 3号点云,通过欧拉角旋转
# 采用Euler角的方法生成旋转角,表示绕y轴旋转90°
thEuler = pcds[3].get_rotation_matrix_from_xyz((0,np.pi/2,0))
pcds[3].rotate(thEuler)
# 4号点云,通过轴角法旋转
th = np.array([0, np.pi/3, 0]).T
thAxis = pcds[4].get_rotation_matrix_from_axis_angle(th)
pcds[4].rotate(thAxis)
# 5号点云,通过四元数旋转
# 通过四元数法生成转角,表示绕x轴旋转180°
quart = np.array([0,0,0,1]).T
thQuart = pcds[5].get_rotation_matrix_from_quaternion(quart)
pcds[5].rotate(thQuart)
# 5绘图函数可以输入点云列表
o3d.visualization.draw_geometries(pcds)
【translate】是用于图像平移,其输入数组为方向平移的值,考虑到这些操作均将作用于对象本身,所操作之前进行了深拷贝。
【paint_uniform_color】用于更改点云颜色,其输入的数组为RGB三个通道的值。
【scale】用于点云缩放,有两个输入参数,分别是缩放比例和缩放后的位置,本例中,将缩放后的点云放置在原来点云的质心处。
和平移、缩放相比,旋转相对复杂,上例共使用了三个旋转函数来实现。
【get_rotation_matrix_from_xyz】可通过轴角表示法生成旋转角,输入参数为欧拉角,有三个分量,对应横滚、俯仰以及航向这三个方向,代表绕轴旋转。考虑一架正在飞行的飞机,以某一时刻前后为x轴、左右为y轴、上下为z轴。则航向角就是飞机前进方向偏离的角度;俯仰角就是飞机头尾姿态的俯仰;横滚角描述的就是飞机翅膀的摆动。
欧拉角用于描述静态角度是没问题的,但表示旋转会导致万向节死锁,简单来说就是飞机的航向角变化90°之后,其横滚轴变成了俯仰轴,导致自由度丢失,而四元数则没有这个顾虑。
设欧拉角为,则四元数可表示为
点云类中的生成旋转矩阵的方法均为静态方法,可在不建立对象的情况下调用。
在演示变换的过程中调用了三个,其前缀均为 get_rotation_matrix_from_
,结尾是 axis_angle
表示通过欧拉角生成旋转矩阵;quaternion
通过四元数;from_xyz
则通过旋转向量。
open3d支持通过不同顺序的xyz数组创建旋转矩阵,由于三个坐标总计有6个组合,故而提供了6个静态方法。例如,针对向量,其创建旋转矩阵的方法为 get_rotation_matrix_from_xyz
;对于,只需将 xyz
换为 yxz
即可,非常方便记忆。
点云框线
open3d提供了多种生成框线的方法,所谓框线,就是一组将点云完全包裹住的线段。如下图所示,其中左侧绿框为轴对齐边框,顾名思义其框线平行于坐标轴;红框为定向边框,即根据点云自身的性质,寻找合适的边框方向;右侧边框为凸包,即选取点云中最外侧的点连接成一个凸多面体。
实现和绘图代码如下
# 定向边框
obb = pcd.get_oriented_bounding_box()
obb.color = [1,0,0]
# 轴对齐边框
aabb = pcd.get_axis_aligned_bounding_box()
aabb.color = [0,1,0]
pcd2 = deepcopy(pcd).translate([3,0,0])
# 凸包
hull, _ = pcd2.compute_convex_hull()
hull_ls = o3d.geometry.LineSet.create_from_triangle_mesh(hull)
o3d.visualization.draw_geometries([pcd, obb, aabb, pcd2, hull_ls])