拟合平面点云
1.点云处理
point_cloud = o3d.geometry.PointCloud() #创建点云对象point_cloud,用于存储和操作点云数据。
point_cloud.points = o3d.utility.Vector3dVector(xyz) # 该函数用于将一维数组、列表或其他可迭代对象中的三维向量数据转换为Open3D库中定义的Vector3dVector类型。
# 剔除无效值
pcd1 = deepcopy(point_cloud)
pcd1 = pcd1.remove_non_finite_points(True, True) # 剔除无效值
pcd2 = deepcopy(pcd1)
res = o3d.geometry.PointCloud.remove_statistical_outlier(pcd2,200, 0.5) # 统计方法剔除
1.1 删除点云中无效的点
remove_non_finite_points(self, remove_nan=True, remove_infinite=True)
无效值包括空值和无限值。空值一般用NaN表示。 当remove_ nan为True时,剔除空值。当remove_ infinite为True时表示去除无限值。
1.2 统计方法剔除
open3d.geometry.PointCloud
remove_statistical_outlier(self, nb_neighbors, std_ratio, print_progress=False)
函数功能:删除距离其邻居较远的点
参数:nb_neighbors (int)
:目标点周围的点数。它指定考虑多少邻居来计算给定点的平均距离;
std_ratio (float)
:标准差比率。它允许根据跨点云的平均距离的标准偏差设置阈值级别。这个数字越低,过滤器就越激进;
print_progress (bool, optional, default=False)
:设置为 True 以打印进度条。
原始点云图
)
处理后点云图
2.使用RANSAC算法拟合平面
plane_model, inliers = pcd2.segment_plane(distance_threshold=error_threshold,
ransac_n=outer_point,
num_iterations=max_iterations)
参数:destance_threshold
定义了一个点到一个估计平面的最大距离,这些距离内的点被认为是内点(inlier),ransac_n
定义了使用随机抽样估计一个平面的点的个数,num_iterations
定义了随机平面采样和验证的频率(迭代次数)。这个函数返回(a,b,c,d)作为一个平面,对于平面上每个点(x,y,z)我们有ax+by+cz+d=0。这个函数还会返回内点索引的列表。
plane_model
返回a,b,c,d值
inliers
返回inlier_cloud,outlier_cloud
注:以RANSAC平面分割为例,由于三个可以确定一个平面, 因此RANSAC会随机选择三个点来构建一个平面, 并用点云中实际上有多少个点落到这个平面上来作为评估这个平面的正确程度。当随机抽样的次数足够多时,我们有较大概率获得所需要的平面。
inlier_cloud
(内点)为红色,outlier_cloud
(离群点)为绿色。
3.最小二乘法优化平面方程参数
def leastsq_plan(points):
def planeerrors(para, points):
"""平面误差"""
a0, a1, a2 = para
return a0 * points[:, 0] + a1 * points[:, 1] + points[:, 2] + a2
tparap = optimize.leastsq(planeerrors, [1, 1, 1], points)
para = tparap[0]
return para
该函数使用优化后点云inlier_cloud拟合平面方程,找到最优的参数值a,b,c,d。
注:也可以使用SVD分解法求解平面点云-------》》》 链接