4. 半径滤波:半径搜索与点数阈值、与统计滤波的对比、适用场景分析

好,咱们接着聊点云滤波。前面讲了统计滤波,今天要聊的半径滤波,其实跟它有点像,但思路完全不同。

说白了,半径滤波的逻辑更直白:在一个给定的球半径内,如果点数不够,我就认为这个点是离群点。嗯,就这么简单。

4.1 半径滤波的核心原理

我习惯把半径滤波叫做“圈地运动”。你想象一下,每个点周围画一个半径为 r 的球,然后数一数这个球里面住了多少个邻居。如果邻居太少,比如少于 k 个,那这个点大概率是个孤魂野鬼,直接干掉。

这里有两个关键参数:

  • 搜索半径 r:这个球要画多大?
  • 点数阈值 k:球里至少要有几个点才算合格?

我在项目中遇到过这样的情况:用统计滤波把大片的离群点去掉了,但总有一些“漏网之鱼”——那些离主体不远不近、刚好卡在统计阈值边缘的点。这时候半径滤波就派上用场了,因为它对局部密度的变化更敏感。

4.2 代码实现与参数调优

直接上代码。PCL 里实现半径滤波非常简单,我一般这么写:

#include <pcl/filters/radius_outlier_removal.h>

pcl::RadiusOutlierRemoval<pcl::PointXYZ> radius_filter;
radius_filter.setInputCloud(cloud);
radius_filter.setRadiusSearch(0.05);      // 半径 5 厘米
radius_filter.setMinNeighborsInRadius(6); // 至少 6 个邻居
radius_filter.filter(*cloud_filtered);

你看,就三行核心代码。但参数怎么设?这里我踩过坑。

避坑指南: 我曾经在扫描一个室内场景时,把半径设成了 0.1 米,阈值设成了 10。结果发现墙角的一些点全被删了。为什么?因为墙角处的点云密度天然就低,10 个邻居的要求太苛刻了。后来我改成 0.08 米、阈值 5,效果就好多了。

所以我的建议是:先看数据,再调参数。你可以先算一下整个点云的平均点间距,半径一般取平均间距的 2-3 倍。阈值的话,我习惯从 3 开始试,不够再往上加。

4.3 与统计滤波的对比

很多新手会问:半径滤波和统计滤波到底选哪个?我直接给你一张对比表,看完就明白了。

对比维度 半径滤波 统计滤波
判断依据 固定半径内的点数 点到邻居的平均距离
对密度变化的敏感度 高(局部密度不均时容易误删) 低(基于全局统计分布)
参数含义 半径 r + 阈值 k 邻居数 k + 标准差倍数 σ
适用场景 密度均匀、孤立点少 密度变化大、噪声分布广
计算效率 较快(只需一次半径搜索) 稍慢(需计算距离统计量)
典型误删情况 边缘点、稀疏区域点 密集区域中的孤立点

你想想看,统计滤波是“看全局”——它算的是所有点的平均距离,然后砍掉那些“太离谱”的。而半径滤波是“看局部”——它只关心这个点周围有没有足够多的兄弟。所以,统计滤波适合处理大范围的稀疏噪声,半径滤波适合清理那些零散的小离群点。

我的实战经验: 在实际项目中,我经常把两个滤波串起来用。先用统计滤波干掉大片的飞点,再用半径滤波清理残余的孤立点。顺序不能反,否则半径滤波会把密集区域的点也误删掉。

4.4 适用场景分析

半径滤波不是万能的,它有自己的“舒适区”。我总结了几个典型场景:

  • 场景一:室内结构化场景
    比如墙面、地面、天花板。这些地方点云密度均匀,半径滤波效果很好。我做过一个办公室重建项目,用半径滤波把桌面上飘着的几个噪点全干掉了,干净利落。
  • 场景二:物体表面细节保留
    如果你要保留物体的边缘和棱角,半径滤波比统计滤波更友好。因为统计滤波会“一刀切”,而半径滤波只删那些真正孤立的点。
  • 场景三:实时性要求高的应用
    半径滤波的计算量小,适合嵌入式设备或需要实时处理的场景。我记得有一次在 Jetson Nano 上跑点云预处理,统计滤波要 30 毫秒,半径滤波只要 15 毫秒。
  • 场景四:不适用的情况
    如果点云密度变化剧烈——比如远处稀疏、近处密集——半径滤波会误删大量远处的点。这时候我建议改用统计滤波,或者先做体素下采样让密度均匀化。

4.5 核心逻辑流程图

下面这张图是我自己画的,把半径滤波的整个流程串起来了。你看一眼就能明白它在干什么。

半径滤波核心逻辑流程图 输入原始点云 步骤1:构建KD树加速搜索 步骤2:设置半径 r 和阈值 k 步骤3:遍历每个点,半径搜索邻居 邻居数 ≥ k ? 是 保留该点 否 删除该点(离群点) 输出滤波后点云

你看,流程其实不复杂。核心就是那个判断:邻居够不够?不够就删。但就是这个简单的逻辑,在实际工程中非常实用。

4.6 参数调优的实用建议

最后,我把自己调参的经验总结成几条,你直接拿去用:

  1. 先粗后细:先用大半径、低阈值试一遍,看看哪些点被删了。再逐步缩小半径、提高阈值。
  2. 可视化验证:每次调参后,一定要把滤波前后的点云叠在一起看。我习惯用 PCL 的 pcl_viewer 或者 CloudCompare,一眼就能看出问题。
  3. 分区域处理:如果点云密度差异大,别想着一个参数打天下。我做过一个项目,把点云按距离分成近、中、远三块,每块单独调参,效果比全局滤波好得多。
  4. 注意边界效应:点云边缘的点,邻居天然就少。如果你发现边缘被削得太狠,可以适当降低阈值,或者用条件滤波做补充。

一句话总结: 半径滤波是点云预处理中的“精确打击武器”。它不擅长处理大范围噪声,但对付那些零散的孤立点,它比统计滤波更精准、更高效。

好了,半径滤波就聊到这儿。下一节我们讲条件滤波,那个更灵活,但用不好也容易翻车。到时候我再分享几个翻车案例给你听。