pclpy 半径滤波实现
- 一、算法原理
- 背景
- 二、代码
- 1.pclpy 官方给与`RadiusOutlierRemoval`
- 2.手写的半径滤波(速度太慢了,用官方的吧)
- 三、结果
- 1.左边为原始点云,右边为半径滤波后点云
- 四、相关数据
一、算法原理
RadiusOutlierRemoval
是一个点云滤波器,用于从点云中去除离群点。它基于给定半径内的邻域点数量来识别和移除离群点。具体来说,对于每个点,它计算其半径范围内的邻域点数量。如果邻域内的点数量小于给定阈值,则认为该点是一个离群点,将其从点云中移除。
图有助于形象化RadiusOutlierRemoval
过滤器对象的作用。用户指定多个邻居,每个索引必须在指定半径内具有这些邻居才能保留在 PointCloud
中。例如,如果指定了 1 个邻居,则只会从 PointCloud
中删除黄色点。如果指定了 2 个邻居,那么黄色和绿色点都将从 PointCloud
中删除。
二、代码
1.pclpy 官方给与RadiusOutlierRemoval
from pclpy import pcl
import numpy as np
def compareCloudShow(cloud1, cloud2):
"""
Args:在一个窗口生成2个窗口可视化点云
cloud1: 点云数据1
cloud2: 点云数据2
"""
viewer = pcl.visualization.PCLVisualizer("viewer") # 建立可刷窗口对象 窗口名 viewer
v0 = 1 # 设置标签名(0, 1标记第一个窗口)
viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v0) # 创建一个可视化的窗口
viewer.setBackgroundColor(0.0, 0.0, 0.0, v0) # 设置窗口背景为黑色
single_color = pcl.visualization.PointCloudColorHandlerCustom.PointXYZ(cloud1, 255.0, 0, 0.0) # 将点云设置为红色
viewer.addPointCloud(cloud1, # 要添加到窗口的点云数据。
single_color, # 指定点云的颜色
"sample cloud1", # 添加的点云命名
v0) # 点云添加到的视图
v1 = 2 # 设置标签名(2代表第二个窗口)
viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v1) # 创建一个可视化的窗口
viewer.setBackgroundColor(255.0, 255.0, 255.0, v1) # 设置窗口背景为白色
single_color = pcl.visualization.PointCloudColorHandlerCustom.PointXYZ(cloud2, 0.0, 255.0, 0.0) # 将点云设置为绿色
viewer.addPointCloud(cloud2, # 要添加到窗口的点云数据。
single_color, # 指定点云的颜色
"sample cloud2", # 添加的点云命名
v1) # 点云添加到的视图
# 设置点云窗口(可移除对点云可视化没有影响)
viewer.setPointCloudRenderingProperties(0, # 设置点云点的大小
1, # 点云像素
"sample cloud1", # 识别特定点云
v0) # 在那个窗口可视化
viewer.setPointCloudRenderingProperties(0, # 设置点云点的大小
1, # 点云像素
"sample cloud2", # 识别特定点云
v1) # 在那个窗口可视化
viewer.addCoordinateSystem(1.0) # 设置坐标轴 坐标轴的长度为1.0
# 窗口建立
while not viewer.wasStopped():
viewer.spinOnce(10)
if __name__ == '__main__':
# 读取点云数据
cloud = pcl.PointCloud.PointXYZ()
reader = pcl.io.PCDReader()
reader.read('res/table_scene_lms400.pcd', cloud)
print("点云数目:", cloud.size())
# 创建ror滤波器(半径滤波)
ror = pcl.filters.RadiusOutlierRemoval.PointXYZ() # 生成ror对象
ror.setInputCloud(cloud) # 处理cloud点云
ror.setRadiusSearch(0.01) # 设置搜索半径
ror.setMinNeighborsInRadius(10) # 阈值
ror.setKeepOrganized(True) # 是指定在滤波过程中是否保持点云的组织结构。当参数设置为False时,表示滤波器将不会保持点云的组织结构,而是直接删除离群点后重新组织点云数据。
cloud_filtered = pcl.PointCloud.PointXYZ() # 建立点云对象
ror.filter(cloud_filtered) # 将处理后的点云放入到 cloud_filtered
# 可视化滤波效果
compareCloudShow(cloud, cloud_filtered)
2.手写的半径滤波(速度太慢了,用官方的吧)
大家可以参考原理,便于理解半径滤波是怎么实现的。
from pclpy import pcl
import numpy as np
def myRadiusOutlier(pcd, radius, MinNeighbors):
"""半径滤波"""
points = pcd.xyz # 将点云转换为numpy数组
save_seeds = [] # 保存筛选后点 不改变点云结构
for seed in points:
# 进行半径邻搜索 可以看open3d 半径最近邻搜索(KD-Tree 和 numpy的两种方法) open3d专栏
index = np.where(((points[:, 0] - seed[0])**2 + (points[:, 1] - seed[1])**2 + (points[:, 2] - seed[2])**2) <= radius**2)[0]
if MinNeighbors < len(index):
save_seeds.append(seed)
if len(save_seeds) != 0:
return pcl.PointCloud.PointXYZ.from_array(save_seeds)
return pcd
if __name__ == '__main__':
# 读取点云数据
cloud = pcl.PointCloud.PointXYZ()
reader = pcl.io.PCDReader()
reader.read('res/happy.pcd', cloud)
print("点云数目:", cloud.size())
cloud_filtered = myRadiusOutlier(cloud, 0.01, 2)
compareCloudShow(cloud, cloud_filtered)
三、结果
1.左边为原始点云,右边为半径滤波后点云
四、相关数据
open3d 半径最近邻搜索open3d 半径最近邻搜索(KD-Tree 和 numpy的两种方法)-CSDN博客