pclpy SOR去除异常值(统计滤波)

一、算法原理

1.背景

激光扫描通常会生成不同点密度的点云数据集。此外,测量误差会导致稀疏的异常值,从而进一步破坏测量结果。这使得局部点云特征的估计变得复杂,例如表面法线或曲率变化,导致计算错误,进而可能导致点云配准失败。其中一些不规则异常值可以通过对每个点的邻域进行统计分析来解决,并修剪不符合特定标准的那些。我们使用基于输入数据集中点到邻居距离分布的计算移除稀疏异常值。对于每个点,我们计算从它到所有邻居的平均距离。通过假设结果分布是具有均值和标准差的高斯分布,

下图显示了稀疏异常值分析和去除的效果:原始数据集显示在左侧,而结果数据集显示在右侧。该图显示了过滤前后点邻域中的平均 k 最近邻距离。

在这里插入图片描述

2.原理

去除分布稀疏的点,对于点云中的每个点,计算到最近k个点的平均距离,然后假设结果构成高斯分布,过滤平均距离大于标准差的点。

参数

sor.setMeanK(k):最近k个点

sor.setStddevMulThresh(阈值):基于标准差的阈值,越小滤除点越多

二、代码

from pclpy import pcl

if __name__ == '__main__':
    # 读取点云数据
    cloud = pcl.PointCloud.PointXYZ()
    reader = pcl.io.PCDReader()  # 设置读取对象
    reader.read('res/table_scene_lms400.pcd', cloud)  # 读取点云保存在cloud中
    print('去除前点云数目:', cloud.size())

    # 设置处理后点云的保存
    cloud_filtered_inliers = pcl.PointCloud.PointXYZ()  # 保存索引后的点云(内点)
    cloud_filtered_outliers = pcl.PointCloud.PointXYZ()  # 去除的点云噪点(外点)

    # 创建sor滤波器
    sor = pcl.filters.StatisticalOutlierRemoval.PointXYZ()  # 创建sor处理对象
    sor.setInputCloud(cloud)  # 将cloud处理
    sor.setMeanK(50)  # 每个点要分析的邻居数
    sor.setStddevMulThresh(1.0)  # 距离查询点的平均距离大于1个标准差的点都将被标记为离群值并删除
    sor.filter(cloud_filtered_inliers)  # sor处理后的点云保存在这里(内点)
    print('内点数目:', cloud_filtered_inliers.size())
    sor.setNegative(True)  # 获得去除的点噪点(外点)
    sor.filter(cloud_filtered_outliers)  # 降去除的点保存在 cloud_filtered_outliers
    print('外点数目:', cloud_filtered_outliers.size())

    # 可视化点云
    viewer = pcl.visualization.PCLVisualizer("3D viewer")  # 建立一个可视化对象,窗口名 3D viewer
    single_color = pcl.visualization.PointCloudColorHandlerCustom.PointXYZ(cloud, 0.0, 255.0, 0.0)  # 设置点云颜色(绿色)
    viewer.addPointCloud(cloud_filtered_outliers, single_color)  # 将颜色和点云数据添加到可刷对象中
    while not viewer.wasStopped():  # 展示可视化对象
        viewer.spinOnce(10)

三、结果

1.原点云

在这里插入图片描述

2.sor处理后的点云(内点)

在这里插入图片描述

3.sor处理后的点云(外点)

在这里插入图片描述

四、相关数据

测试数据链接:https://pan.baidu.com/s/1am-4qlxuX_l6uoDeIbpPrA
提取码:ffs2

  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个用 PCL 和 C 实现先读取点云,再点云统计滤波,再点云计算平面度,再点云输保存的代码示例: ``` #include <iostream> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/filters/statistical_outlier_removal.h> #include <pcl/features/normal_3d.h> #include <pcl/features/normal_3d_omp.h> #include <pcl/features/normal_3d.h> #include <pcl/surface/convex_hull.h> int main(int argc, char** argv) { // 读取点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::PCDReader reader; reader.read("input_cloud.pcd", *cloud); // 点云统计滤波 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>); pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor; sor.setInputCloud(cloud); sor.setMeanK(50); sor.setStddevMulThresh(1.); sor.filter(*cloud_filtered); // 点云计算法线 pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>); pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud(cloud_filtered); ne.setSearchMethod(tree); ne.setKSearch(20); ne.compute(*normals); // 点云计算平面度 pcl::ConvexHull<pcl::PointXYZ> chull; chull.setInputCloud(cloud_filtered); pcl::PointCloud<pcl::PointXYZ>::Ptr hull(new pcl::PointCloud<pcl::PointXYZ>); chull.reconstruct(*hull); float area = pcl::calculatePolygonArea(*hull); // 点云输保存 pcl::PCDWriter writer; writer.write("output_cloud.pcd", *cloud_filtered); return ; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云杂项

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

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

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

打赏作者

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

抵扣说明:

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

余额充值