pclpy 半径滤波实现

一、算法原理

  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博客

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云杂项

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值