第4章 点云预处理:离群点滤波、体素滤波降采样、直通滤波(ROI提取)

点云预处理,说白了就是给雷达数据「洗个澡」。

我刚开始做毫米波雷达的时候,拿到原始点云直接丢进聚类算法,结果惨不忍睹——全是噪声点、鬼影点,聚类出来的目标根本没法看。后来才明白,预处理这一步省不得,而且顺序也有讲究。

4.1 离群点滤波:把「孤魂野鬼」请出去

毫米波雷达的点云里,经常会出现一些孤立的噪点。可能是多径反射,可能是热噪声,也可能是某个角度突然闪了一下。这些点周围没有邻居,聚类时却会干扰结果。

常用的方法:统计离群点滤波

原理很简单:对每个点,计算它到K个最近邻的平均距离。如果这个距离超过全局均值+若干倍标准差,就判定为离群点。

核心参数:

  • K(邻居数):我一般设10-20。太小了容易误判,太大了计算慢。
  • 标准差倍数(std_ratio):1.0到2.0之间。倍数越小,剔除得越狠。

我的经验:在高速场景下,我会把std_ratio设到1.5左右。因为运动目标周围的点本身分布就稀疏,倍数太大反而把真实目标剔除了。低速场景可以放宽到2.0。

// C++ 示例:PCL 统计离群点滤波
#include <pcl/filters/statistical_outlier_removal.h>

pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
sor.setInputCloud(cloud);
sor.setMeanK(15);          // 邻居数
sor.setStddevMulThresh(1.5); // 标准差倍数
sor.filter(*cloud_filtered);

注意:离群点滤波会改变点云数量。如果你后续要做基于索引的操作(比如跟踪),记得保存原始索引映射。

4.2 体素滤波降采样:给点云「减肥」

64线激光雷达一帧能出几十万个点,毫米波雷达虽然少一些,但长时间累积下来数据量也不小。体素滤波就是用一个三维网格把空间划分成小方块,每个方块里只保留一个代表点。

为什么需要降采样?

  • 减少计算量——聚类、识别都能快不少
  • 均匀化点云分布——避免某些区域点太密
  • 去除冗余——相邻点其实信息量差不多

体素大小的选择

这个很关键。我踩过坑:体素设太大,远处的行人直接消失了;设太小,降采样效果不明显。

场景 推荐体素大小 说明
高速公路 0.3m - 0.5m 目标大、距离远,可以粗一点
城市道路 0.2m - 0.3m 行人、自行车需要细节
停车场/室内 0.1m - 0.2m 近距离、小目标多
// C++ 示例:PCL 体素滤波
#include <pcl/filters/voxel_grid.h>

pcl::VoxelGrid<pcl::PointXYZ> vg;
vg.setInputCloud(cloud);
vg.setLeafSize(0.25f, 0.25f, 0.25f); // 体素边长
vg.filter(*cloud_downsampled);

我个人习惯:先做体素滤波,再做离群点滤波。因为降采样后点云更规整,离群点检测的统计特性更稳定。顺序反了的话,离群点滤波会先剔除一些点,体素滤波又可能把剩下的点「压」得更密,效果反而不好。

4.3 直通滤波:只关注你关心的区域

直通滤波,说白了就是「切一刀」。在某个坐标轴方向设定一个范围,范围内的点留下,范围外的扔掉。

典型应用场景:

  • ROI提取:比如我只关心车前50米、左右各10米的区域
  • 去除地面:在Z轴方向切掉地面以下和车顶以上的点
  • 去除后方点:在X轴方向只保留正前方的点

为什么会用到直通滤波?你想想看,毫米波雷达有时候会打到地面、护栏、甚至天上的飞鸟。这些点对目标识别毫无意义,反而增加计算负担。

// C++ 示例:PCL 直通滤波
#include <pcl/filters/pass_through.h>

pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("x");      // 沿X轴
pass.setFilterLimits(0.0, 50.0);   // 保留0到50米
pass.filter(*cloud_roi);

// 再切Z轴,去除地面和车顶
pass.setFilterFieldName("z");
pass.setFilterLimits(-1.5, 2.5);   // 假设雷达安装高度1.5m
pass.setInputCloud(cloud_roi);
pass.filter(*cloud_final);

避坑指南:我曾经在高速项目上把直通滤波的范围设得太紧,结果弯道上的目标被切掉了。后来我改成动态ROI——根据车速和转向角实时调整滤波范围。嗯,这个后面讲到跟踪时会细说。

4.4 预处理流程总结

我一般按这个顺序走:

  1. 直通滤波——先砍掉不关心的区域,减少后续计算量
  2. 体素滤波——降采样,让点云更均匀
  3. 离群点滤波——最后清理残余噪声

当然,这不是铁律。如果你的场景点云特别稀疏,体素滤波可以跳过。如果噪声特别多,离群点滤波可以多做一轮。

一句话总结:预处理的目标不是「让点云变好看」,而是「让后续算法能正常工作」。每个滤波器的参数都要根据你的雷达型号、安装位置、应用场景来调。没有万能参数,只有不断试错。

下一章我们会聊聚类算法。预处理做好了,聚类才能事半功倍。否则,你就是在垃圾堆里找宝藏——累死也找不到。