【点云处理技术之PCL】滤波器——离群点滤波(statisticalOutlierRemoval、ConditionalRemoval 和RadiusOutlinerRemoval)

1. 离群点滤波器–statisticalOutlierRemoval

通常激光点云往往会伴随着一些噪声的存在,而这会使局部点云特征(如曲面法线或曲率变化)的估计变得复杂,从而导致错误的值,进而可能导致点云配准失败。StatisticalOutlierRemoval滤波器,是一种使用统计化的方法删除离群点的滤波器

这种滤波器对每个点的邻域进行统计分析,并对不符合统计结果的点进行删除,统计方法是根据数据的邻域距离进行分析出来的结果。对于每一个点都会计算它到邻域的平均距离,并假设所有的点满足高斯分布,计算出来的平均值如果不满足全局距离下的高斯分布,则对它进行修建

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/statistical_outlier_removal.h>

int main(int argc, char **argv)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);//读取pcd用
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);//滤波后的结果

    // Fill in the cloud data
    pcl::PCDReader reader;
    reader.read<pcl::PointXYZ>("../../pcd/table_scene_lms400.pcd", *cloud); //读取pcd点云

    std::cerr << "Cloud before filtering: " << std::endl;
    std::cerr << *cloud << std::endl;

    // Create the filtering object
    //设置滤波器对象
    pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud);    //输入点云
    sor.setMeanK(50);            //设置领域点的个数
    sor.setStddevMulThresh(1.0); //设置离群点的阈值
    sor.filter(*cloud_filtered); //滤波后的结果

    std::cerr << "Cloud after filtering: " << std::endl;
    std::cerr << *cloud_filtered << std::endl;

    //获取删除离群点之后的值
    pcl::PCDWriter writer;
    writer.write<pcl::PointXYZ>("../../pcd/table_scene_lms400_inliers.pcd", *cloud_filtered, false);

    sor.setNegative(true); //获取离群点
    sor.filter(*cloud_filtered);
    writer.write<pcl::PointXYZ>("../../pcd/table_scene_lms400_outliers.pcd", *cloud_filtered, false);

    return (0);
}

输出结果如下,使用离群点删除之后,点云数量有所减少。

Cloud before filtering: 
points[]: 460400
width: 460400
height: 1
is_dense: 1
sensor origin (xyz): [0, 0, 0] / orientation (xyzw): [0, 0, 0, 1]

Cloud after filtering: 
points[]: 451410
width: 451410
height: 1
is_dense: 1
sensor origin (xyz): [0, 0, 0] / orientation (xyzw): [0, 0, 0, 1]

下面来看看可视化的效果,原图效果如下:
在这里插入图片描述
删除离群点之后的效果如下,很明显,点云分布比之前干净了很多。

在这里插入图片描述
被删除的离群点可视化效果如下:
在这里插入图片描述

2. 半径搜索滤波和条件搜索滤波–RadiusOutlinerRemoval和ConditionalRemoval

  • ConditionalRemoval滤波器:可以一次删除满足对输入的点云设定的一个或多个条件指标的所有的数据点

  • RadiusOutlinerRemoval滤波器:它可以删除在输入点云一定范围内没有至少达到足够多近邻的所有数据点.

便于理解RadiusOutlinerRemoval滤波器,如下图所示,假如给定固定的搜索半径d,如果搜索的点云个数为1,那么黄色的点将被删除,如果搜索的点为2,那么黄色和绿色的点将被删除。
在这里插入图片描述

#include <iostream>
#include <pcl/point_types.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/conditional_removal.h>

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
        exit(0);
    }
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

    // Fill in the cloud data
    cloud->width = 5;
    cloud->height = 1;
    cloud->resize(cloud->width * cloud->height);

    for (auto &point : *cloud)
    {
        point.x = 1024 * rand() / (RAND_MAX + 1.0f);
        point.y = 1024 * rand() / (RAND_MAX + 1.0f);
        point.z = 1024 * rand() / (RAND_MAX + 1.0f);
    }

    //RadiusOutlierRemoval滤波
    if (strcmp(argv[1], "-r") == 0)
    {
        pcl::RadiusOutlierRemoval<pcl::PointXYZ> outrem;
        // build the filter
        outrem.setInputCloud(cloud);//输入点云
        outrem.setRadiusSearch(0.8);//设置滤波搜索半径
        outrem.setMinNeighborsInRadius(2);//设置半径内的至少的点云个数
        outrem.setKeepOrganized(true);
        // apply filter
        outrem.filter(*cloud_filtered);//开始滤波,并获取滤波点云
    }
    //ConditionAnd滤波
    else if (strcmp(argv[1], "-c") == 0)
    {
        // build the condition
        pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>());//创建条件对象
        
        //为条件添加算子
        //添加在Z字段上大于0的比较算子
        range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::GT, 0.0)));
        //添加在Z字段上小于0.8的比较算子
        range_cond->addComparison(pcl::FieldComparison<pcl::PointXYZ>::ConstPtr(new pcl::FieldComparison<pcl::PointXYZ>("z", pcl::ComparisonOps::LT, 0.8)));
        // build the filter
        pcl::ConditionalRemoval<pcl::PointXYZ> condrem;
        condrem.setCondition(range_cond);
        condrem.setInputCloud(cloud);
        condrem.setKeepOrganized(true);
        // apply filter
        condrem.filter(*cloud_filtered);
    }
    else
    {
        std::cerr << "please specify command line arg '-r' or '-c'" << std::endl;
        exit(0);
    }
    std::cerr << "Cloud before filtering: " << std::endl;
    for (const auto &point : *cloud)
        std::cerr << "    " << point.x << " "
                  << point.y << " "
                  << point.z << std::endl;
    // display pointcloud after filtering
    std::cerr << "Cloud after filtering: " << std::endl;
    for (const auto &point : *cloud_filtered)
        std::cerr << "    " << point.x << " "
                  << point.y << " "
                  << point.z << std::endl;
    return (0);
}

使用 ./remove_outliers -r 方式运行半径搜索滤波方式

使用./remove_outliers -c 方式运行条件搜索滤波方式


参考:

https://pcl.readthedocs.io/projects/tutorials/en/latest/statistical_outlier.html#statistical-outlier-removal

https://pcl.readthedocs.io/projects/tutorials/en/latest/remove_outliers.html#remove-outliers

  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在问题中,您提到了AttributeError: module 'pcl' has no attribute 'StatisticalOutlierRemoval'的错误。这个错误通常表示在导入pcl模块时出现问题,因为pcl模块没有名为StatisticalOutlierRemoval的属性。要解决这个问题,您可以尝试以下几个步骤: 1. 检查模块安装:首先,请确保您已经正确安装了pcl模块。您可以使用命令行或包管理器来安装pcl。如果您使用的是pip,可以运行"pip install pcl"来安装pcl模块。 2. 检查模块版本:如果pcl模块已经安装,那么请确保您正在使用最新版本。您可以使用命令"pip show pcl"来检查当前安装的版本,并使用"pip install --upgrade pcl"来升级到最新版本。 3. 检查属性名称:如果确保模块已经正确安装且版本已经升级,那么请确保您在代码中正确地使用了属性名称。比如,对于pcl模块中的StatisticalOutlierRemoval类,您应该使用"pcl.StatisticalOutlierRemoval"来引用。 4. 检查导入语句:确认您的导入语句是否正确。对于pcl模块,正确的导入语句应该是"import pcl"。 如果您按照上述步骤仍然无法解决问题,那么可能是由于其他原因导致的。您可以查找更多关于该错误的信息,并尝试其他解决方法,或者咨询pcl模块的官方文档或社区以获得进一步的支持。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [成功解决AttributeError: module ‘skimage‘ has no attribute ‘io](https://blog.csdn.net/qq_41185868/article/details/121643945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [AttributeError: module 'tensorflow.compat.v1' has no attribute '](https://download.csdn.net/download/qq_38766019/86272235)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

非晚非晚

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

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

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

打赏作者

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

抵扣说明:

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

余额充值