PCL入门系列 —— RadiusOutlierRemoval 点云半径滤波

PCL入门系列 —— RadiusOutlierRemoval 点云半径滤波


前言

随着工业自动化、智能化的不断推进,机器视觉(2D/3D)在工业领域的应用和重要程度也同步激增(识别、定位、抓取、测量,缺陷检测等),而针对不同作业场景进行解决方案设计时,通常会借助PCL、OpenCV、Eigen等简单方便的开源算法库进行方案的快速验证和迭代以满足作业场景下的目标需求。

为了让对工业机器视觉方向感兴趣的同学能够少走一些弯路,故推出了此一系列简易入门教程示例,让初次使用者能够最简单直观地感受到当前所用算法模块的执行效果。

后续会逐步扩增与工业机器视觉相关的一些其它内容,如:

项目案例剖析场景数据分析基础算法模块相机评测 等;

如有兴趣可加入群聊(若入群二维码被屏蔽,则可以通过Q群(1032861997)或评论、私信博主“群聊”,邀请入群),与同道同学及圈内同行一起交流讨论。

在这里插入图片描述


程序说明

展示 RadiusOutlierRemoval 半径滤波效果;

输出结果

在这里插入图片描述

代码示例

/*
 * @File: radius_outlier_removal.cpp
 * @Brief: pcl course
 * @Description: 展示RadiusOutlierRemoval半径滤波效果
 * @Version: 0.0.1
 * @Author: MuYv
 */
#include <iostream>
#include <string>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/visualization/pcl_visualizer.h>



int main(int argc, char** argv){
    if(argc != 2){
        std::cout<<"Usage: exec cloud_file_path"<<std::endl;
        return -1;
    }
    const std::string kCloudFilePath = argv[1];  // ../clouds/table_scene.pcd

    // 定义变量
    pcl::PointCloud<pcl::PointXYZ>::Ptr \
                cloud_src(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PointCloud<pcl::PointXYZ>::Ptr \
                cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>());

    // 成功返回0,失败返回-1
    if(-1 == pcl::io::loadPCDFile(kCloudFilePath,*cloud_src)){
        std::cout<<"load pcd file failed. please check it."<<std::endl;
        return -2;
    }

    // 创建半径滤波(模板)类对象
    pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror;
    // 设置输入点云
    ror.setInputCloud(cloud_src);
    // 设置搜索半径
    ror.setRadiusSearch(0.03f);
    // 设置半径范围内的最少点数阈值
    ror.setMinNeighborsInRadius(20);
    // 执行滤波,并带出结果数据
	ror.filter(*cloud_filtered);  //保存滤波结果到cloud_filtered

    // 创建可视化对象
    pcl::visualization::PCLVisualizer viewer("viewer");

    // 将当前窗口,拆分成横向的2个可视化窗口,以viewport区分(v1/v2)
    int v1; 
    int v2;
    //窗口参数分别对应 x_min, y_min, x_max, y_max, viewport
    viewer.createViewPort(0.0, 0.0, 0.5, 1.0, v1);  
    viewer.createViewPort(0.5, 0.0, 1.0, 1.0, v2);

    // 添加2d文字标签
    viewer.addText("v1", 10,10, 20, 1,0,0, "viewport_v1", v1);
    viewer.addText("v2", 10,10, 20, 0,1,0, "viewport_v2", v2);

    // 添加坐标系
    viewer.addCoordinateSystem(0.5);    // 单位:m

    // 设置可视化窗口背景色
    viewer.setBackgroundColor(0.2,0.2,0.2);     // r,g,b  0~1之间

    // 向v1窗口中添加点云
    viewer.addPointCloud(cloud_src,"cloud_src",v1);
    // // 根据点云id,设置点云可视化属性,此处将可视化窗口中的点大小调整为2级
    // viewer.setPointCloudRenderingProperties \
    //         (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud_src");

    // 向v2窗口中添加点云
    viewer.addPointCloud(cloud_filtered,"cloud_filtered",v2);
    // // 根据点云id,设置点云可视化属性,此处将可视化窗口中的点大小调整为2级
    // viewer.setPointCloudRenderingProperties \
    //         (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "cloud_filtered");

    // 关闭窗口则退出
    while(!viewer.wasStopped()){
        viewer.spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;
}

总结

与StatisticalOutlierRemoval统计滤波类似,通过判定指定半径内的点数量是否满足阈值来判定是否为离群点,进而进行剔除,达到滤波的目的;


注:部分测试所用点云数据来源于网络,如有侵权,请联系博主删除,谢谢。

### 点云半径滤波算法原理 点云半径滤波(Radius Outlier Removal)是一种用于去除点云数据中离群点的常用方法。其基本思想是基于邻域搜索,统计每个点周围指定半径范围内的邻近点数量,并根据预设阈值判断当前点是否为离群点。若某点周围的邻近点数量低于设定的阈值,则认为该点是离群点并被移除。 在PCL库中,`pcl::RadiusOutlierRemoval` 类实现了这一功能。它通过设置两个关键参数:**搜索半径(radius)** 和 **最小邻近点数(min_neighbors)** 来定义离群点的标准。具体来说,如果某个点在其指定半径范围内找到的邻近点数量少于 `min_neighbors`,则将其视为离群点并从点云中移除[^3]。 ### 使用案例 以下是一个使用PCL库实现点云半径滤波的代码示例: ```cpp #include <pcl/point_types.h> #include <pcl/filters/radius_outlier_removal.h> // 定义点类型 using PointT = pcl::PointXYZ; int main(int argc, char** argv) { // 创建输入点云 pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>); pcl::PointCloud<PointT>::Ptr cloud_filtered(new pcl::PointCloud<PointT>); // 填充点云数据(此处省略具体填充逻辑) // ... // 创建半径滤波器对象 pcl::RadiusOutlierRemoval<PointT> outrem; outrem.setInputCloud(cloud); outrem.setRadiusSearch(0.1); // 设置搜索半径为0.1米 outrem.setMinNeighborsInRadius(5); // 设置最少邻近点数为5 // 执行滤波操作 outrem.filter(*cloud_filtered); // 输出结果点云 std::cerr << "点云数量: " << cloud->size() << " -> 滤波点云数量: " << cloud_filtered->size() << std::endl; return 0; } ``` 上述代码首先创建了输入点云和输出点云的对象,接着实例化了一个 `pcl::RadiusOutlierRemoval` 对象,并设置了滤波所需的参数。最后调用 `filter` 方法执行滤波操作,得到过滤后的点云数据[^3]。 ### 优缺点分析 - **优点**: - 算法简单且易于实现。 - 能够有效去除稀疏分布的离群点。 - 参数灵活,可根据实际需求调整。 - **缺点**: - 对于密集区域中的离群点效果有限。 - 需要合理选择搜索半径和最小邻近点数,否则可能导致过度滤波或不足滤波
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值