第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 预处理流程总结
我一般按这个顺序走:
- 直通滤波——先砍掉不关心的区域,减少后续计算量
- 体素滤波——降采样,让点云更均匀
- 离群点滤波——最后清理残余噪声
当然,这不是铁律。如果你的场景点云特别稀疏,体素滤波可以跳过。如果噪声特别多,离群点滤波可以多做一轮。
一句话总结:预处理的目标不是「让点云变好看」,而是「让后续算法能正常工作」。每个滤波器的参数都要根据你的雷达型号、安装位置、应用场景来调。没有万能参数,只有不断试错。
下一章我们会聊聚类算法。预处理做好了,聚类才能事半功倍。否则,你就是在垃圾堆里找宝藏——累死也找不到。