在点云处理中,除了之前介绍过的基于统计的离群点去除(pcl::StatisticalOutlierRemoval)方法,PCL库还提供了另一种实用的过滤器——半径滤波。
1. RadiusOutlierRemoval 原理
pcl::RadiusOutlierRemoval 类(简称ROR算法)的核心原理基于局部密度属性:在空间中,正常的点往往聚集分布,其周围邻居点数量较多;而孤立的异常点因远离点云主体,其周围邻居点数量则非常稀少。
该算法的执行步骤如下:
- 半径搜索:对于点云中的每个目标点,搜索其指定半径范围内的所有邻居点。
- 邻居计数:统计该目标点在指定半径范围内的邻居点数量。
- 异常判定:若邻居点数量低于设定的阈值,则判定该点为异常值并予以剔除;反之,则保留为正常点。
可以看到,其处理流程与统计滤波(SOR)基本一致,主要区别在于判断依据从基于距离的统计分析,变为了计算指定半径内的邻居数量。
与SOR类似,pcl::RadiusOutlierRemoval 类也新增了4个关键方法,用于设置和获取ROR算法的核心参数:搜索半径和最小邻居数量。
//设置搜索半径
//@param radius 搜索半径
void setRadiusSearch(double radius);
//获取搜索半径
//@return 搜索半径
double getRadiusSearch();
//设置最小邻居数量
//@param min_pts 最小邻居数量
void setMinNeighborsInRadius(int min_pts);
//获取最小邻居数量
//@return 最小邻居数量
int getMinNeighborsInRadius();
了解原理后,如何调整这两个参数以获得最佳去噪效果呢?
- 搜索半径:这个值决定了邻居搜索的空间范围。半径越大,搜索范围越广,能覆盖的邻居点可能越多,但计算量也会增加;半径越小,搜索范围越窄,对局部密度的变化越敏感。
- 最小邻居数量:这个值决定了异常判定的严格程度。数量设置得越大,判定标准越严格(更多点会被认为是离群点);反之,设置得越小则标准越宽松。通常建议在
[5, 30] 范围内选择,具体需根据点云密度和去噪需求调整。
结合个人经验,分享一个实用的参数调整策略:
-
先确定搜索半径:估算点云的平均点间距,将搜索半径设置为平均点间距的3到5倍。估算平均点间距可以:
- 计算点云包围盒体积,除以总点数得到平均体积,再开立方得到近似平均间距。
- 对点云进行采样,计算每个点到其最近邻点的距离,然后求平均值。
-
再调整最小邻居数量:固定搜索半径,通过观察滤波结果来调试此参数:
- 如果去噪不彻底(残留的异常点较多),可适当增大最小邻居数量(例如从10增加到15)。
- 如果点云细节丢失严重(如边缘点被误剔除),则应适当减小该值(例如从10减少到5)。
- 对于高密度点云,建议设置较大的值(15-30);对于低密度点云,则建议设置较小的值(5-15)。
2. 代码示例
为了更直观地展示如何调用ROR算法,下面提供一个完整的C/C++示例代码:
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
int main(){
// 加载点云数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("input.pcd", *cloud_in);
// 1. 初始化ROR滤波器对象
pcl::RadiusOutlierRemoval<pcl::PointXYZ> ror;
// 2. 设置输入点云
ror.setInputCloud(cloud_in);
// 3. 配置核心参数
ror.setRadiusSearch(0.1); // 设定搜索半径
ror.setMinNeighborsInRadius(10); // 设定最小邻居数量
// 可选:保留离群点而非正常点
// ror.setNegative(true);
// 4. 执行滤波运算,输出去噪后点云
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out(new pcl::PointCloud<pcl::PointXYZ>);
ror.filter(*cloud_out);
// 5. 可选:获取被剔除异常点的索引
std::vector<int> indices;
ror.getRemovedIndices(indices); // indices存储异常点在原始点云中的索引
// 保存滤波结果
pcl::io::savePCDFile("output.pcd", *cloud_out);
return 0;
}
3. 总结
本文详细介绍了PCL中 pcl::RadiusOutlierRemoval 半径滤波器的核心算法原理、关键参数的作用以及实用的参数调优策略,并提供了可直接运行的代码示例。掌握这种基于局部密度的滤波方法,能有效提升点云数据的质量,为后续的配准、分割等处理步骤打下良好基础。如果你想查看更多点云处理或相关的技术实战文章,欢迎访问云栈社区,与其他开发者交流学习。
|