统计滤波器主要是用于去除明显的离群点:离群点特征在空间中分布稀疏,定义某处点云小于某个密度,即点云无效。因此我们要计算每个点到其最近的K个点平均距离,则点云中所有点的距离应构成高斯分布,根据全部点集的均值和标准差,计算距离阈值,剔除阈值之外的点。
(1)使用open3d中的函数来实现
import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud('013205.pcd',remove_nan_points = True,remove_infinite_points = True)
print('原始点云个数是:',np.array(pcd.points).shape[0])
o3d.visualization.draw_geometries([pcd])
cl,index = pcd.remove_statistical_outlier(nb_neighbors = 50,std_ratio= 1.0)
new_cloud = pcd.select_by_index(index)
o3d.visualization.draw_geometries([new_cloud])
(2)自己写代码实现:
遍历全部点云数据,首先计算每个点到其他K个点的平均距离,然后计算该点对全部点集的均值和标准差,根据均值和标准差来计算阈值,根据阈值将符合条件的点留下,组成新的点云输出。
import open3d as o3d
import numpy as np
pcd = o3d.io.read_point_cloud('013205.pcd',remove_nan_points = True,remove_infinite_points = True)
print('原始点云个数是:',np.array(pcd.points).shape[0])
o3d.visualization.draw_geometries([pcd])
def statistical_outlier(cloud,k = 50,threshold = 2.0):#自己写一个统计滤波器
#计算每个点到领域k内的平均距离di
cloud_kdtree = o3d.geometry.KDTreeFlann(cloud)
di = []
new_cloud = []#用于存放新的点云集
for i in range(np.array(cloud.points).shape[0]):
[k,idx,_] = cloud_kdtree.search_knn_vector_3d(cloud.points[i],k)#k近邻搜索,拿到k个点的index,第一个点是搜索本身
#计算K邻域的欧式距离
eucDistance = [np.linalg.norm(np.array(cloud.points)[j] - np.array(cloud.points)[idx[0]]) for j in np.array(idx[1:])]
eucdistance_mean = np.mean(eucDistance,axis=0)#计算出均值
di.append(eucdistance_mean)
#计算整个点集的均值和标准差
distance = [np.linalg.norm(np.array(cloud.points)[j] - np.array(cloud.points)[idx[0]]) for j in range(np.array(cloud.points).shape[0])]
cloud_points_mean = np.mean(distance,axis=0)
cloud_points_std = np.std(distance)#计算出标准差
#计算距离阈值
dmax = cloud_points_mean + threshold*cloud_points_std
dmin = cloud_points_mean - threshold*cloud_points_std
#判断点是否符合距离阈值,符合则留下
if dmin <= di[i] <= dmax :
new_cloud.append(cloud.points[i])
new_pcd = o3d.geometry.PointCloud()
points = o3d.utility.Vector3dVector(np.array(new_cloud))
new_pcd.points = points
o3d.io.write_point_cloud('statistical_deal_points.pcd',new_pcd,True)
o3d.visualization.draw_geometries([new_pcd])
statistical_outlier(pcd,50,1.0)
|