4、点云预处理:点云滤波、降采样、地面去除与感兴趣区域提取
各位同学,咱们今天聊聊点云预处理。说实话,这是整个感知管线里最「脏」最累的活,但也是决定后续算法成败的关键一步。
我刚开始做自动驾驶时,总觉得原始点云数据挺干净的,直接丢给检测算法就行。结果呢?一跑起来,各种噪点、离群点、地面点混在一起,检测框满天飞。后来我才明白——预处理做不好,后面全是白忙活。
4.1 点云滤波:把「脏数据」洗干净
激光雷达采集的点云,说白了就是一堆三维坐标点。但受限于传感器精度、环境干扰,里面总混着不少「垃圾数据」。
常见的滤波手段有这几种:
- 直通滤波(PassThrough Filter):按坐标轴范围切一刀。比如我只关心前方50米内的点,那就把x > 50的点全扔掉。简单粗暴,但很实用。
- 体素滤波(Voxel Filter):把空间划分成小立方体,每个立方体只保留一个代表点。这其实是降采样,但也能起到平滑滤波的作用。
- 统计滤波(Statistical Outlier Removal):计算每个点周围邻居的平均距离,如果某个点离邻居太远,就判定为离群点干掉。我在项目中遇到过,雨雪天气下这个滤波器特别管用。
- 半径滤波(Radius Outlier Removal):设定一个半径,如果某个点周围邻居数量少于阈值,就干掉。适合去除稀疏的噪点。
我的经验:直通滤波和统计滤波是黄金搭档。先用直通把范围框定,再用统计滤波去除飞点。我一般把统计滤波的邻居数设为20,标准差倍数设为1.0,效果不错。
4.2 降采样:别让数据撑爆你的算力
64线激光雷达一秒钟能产生130万个点。你想想看,如果每帧都全量处理,GPU都得冒烟。所以降采样是必须的。
常用的降采样方法:
- 体素降采样(Voxel Grid Downsampling):把空间划分成固定大小的体素网格,每个网格内只保留一个点(通常是重心或中心点)。体素大小一般设为0.1m~0.5m。
- 随机降采样(Random Downsampling):随机扔掉一部分点。简单,但可能丢失关键结构信息。
- 基于距离的降采样:近处保留多点,远处少保留。因为近处需要更精细的感知。
// PCL中的体素降采样示例
pcl::VoxelGrid<pcl::PointXYZ> voxel_filter;
voxel_filter.setInputCloud(cloud);
voxel_filter.setLeafSize(0.2f, 0.2f, 0.2f); // 体素大小20cm
voxel_filter.filter(*cloud_filtered);
注意:体素大小不是越小越好。设成0.05m,点云还是太密;设成0.5m,可能把路沿这种细长结构都抹平了。我一般从0.2m开始调,根据实际场景微调。
4.3 地面去除:把「路」和「障碍物」分开
这是预处理里最核心的一步。为什么?因为地面点占了点云总量的40%~60%,如果不去掉,后续的聚类、检测都会被地面点干扰。
我常用的地面去除方法:
- 平面拟合(RANSAC):假设地面是一个平面,用RANSAC算法拟合出平面方程,然后去掉所有在平面上的点。简单,但遇到坡道就抓瞎。
- 射线法(Ray Ground Filter):把点云按角度分成射线,每条射线上找最低点作为地面候选。适合非平坦地面。
- PatchWork:把空间分成多个同心圆环区域,每个区域独立拟合地面。这是目前工业界比较流行的方案。
我曾经在一条有坡度的匝道上测试RANSAC,结果把整个坡面都当成地面去掉了,导致坡上的车辆全部被误判为地面点。嗯,从那以后我再也不敢在非平坦场景下只用RANSAC了。
避坑指南:地面去除的阈值设置很关键。高度阈值设太大,会把低矮障碍物(如路沿、减速带)也去掉;设太小,地面点去不干净。我一般设0.2m~0.3m,然后根据实车数据微调。
4.4 感兴趣区域提取:只关注该关注的
说白了,就是划定一个三维空间范围,只保留这个范围内的点。比如我们的车在高速上跑,你关心的是前方200米、左右各3个车道内的障碍物。再远的点,对当前决策没意义。
ROI提取的常见策略:
- 矩形ROI:按车辆坐标系,划定一个长方体范围。比如x方向[-10, 100]米,y方向[-15, 15]米,z方向[-2, 3]米。
- 扇形ROI:以车为中心,划定一个扇形区域。适合弯道场景。
- 车道级ROI:结合高精地图或车道线检测,只保留当前车道及相邻车道内的点。精度最高,但依赖地图。
// 矩形ROI提取示例
pcl::PassThrough<pcl::PointXYZ> pass;
pass.setInputCloud(cloud);
pass.setFilterFieldName("x");
pass.setFilterLimits(-10.0, 100.0); // 前方100米,后方10米
pass.filter(*cloud_roi);
我的习惯:ROI范围不是越大越好。范围太大,计算量上去了,还容易引入远处的噪点。我一般根据车速动态调整——车速快时ROI拉长,车速慢时ROI缩短。
4.5 知识体系总览
下面这张图,我把整个点云预处理的流程串起来了。你一看就明白:
你看,整个流程是串行的。每一步都在为下一步做准备。滤波去噪点,降采样减负担,地面去除清障碍,ROI提取定范围。四步走完,点云就从「原始数据」变成了「可用数据」。
核心要点:预处理不是越复杂越好。我见过有人把预处理搞了七八步,结果每步都在丢信息,最后点云都快没了。我的原则是——够用就行,能少一步就少一步。
好了,点云预处理就聊到这儿。记住,这四步是基本功,但每一步都有坑。多在实际数据上跑跑,你就能找到最适合自己场景的参数组合。