在机器人系统中,激光雷达(LiDAR)产生的原始点云数据量非常庞大,往往包含几十万到上百万个点。如果直接用于聚类、检测、匹配,将造成计算负担过重、实时性降低。
因此,我们需要对点云进行滤波与预处理(Filtering & Preprocessing),以去除无效点、降低数据量、增强关键特征。
本文将系统介绍点云处理中的三个核心步骤:
- 体素下采样(VoxelGrid Downsampling)
- ROI 区域裁剪(Region of Interest Cropping)
- 地面点云分割(Ground Segmentation)
一、体素下采样(VoxelGrid Downsampling)
1.1 为什么要进行下采样
激光雷达采样密度高、数据量大,若直接使用原始点云:
- 计算量大,影响实时性;
- 相邻点空间分布过密,信息冗余;
- 聚类或拟合算法耗时严重。
体素下采样(VoxelGrid) 的核心思想是:
将点云划分为立方体小格(Voxel),在每个体素中仅保留一个代表点(通常为该体素内所有点的重心)。
这样既能大幅减少点云数量,又能保持整体几何结构。
1.2 实现原理
假设每个体素的边长为 (leaf_size_x, leaf_size_y, leaf_size_z):
- 将整个点云空间划分为体素网格;
- 对每个体素内的所有点,计算平均坐标;
- 以该平均点代表该体素。
1.3 核心代码
cpp
voxel.setInputCloud(cloud_in); // 输入点云
voxel.setLeafSize(0.1f, 0.1f, 0.1f); // 体素大小(单位: 米)
voxel.filter(*cloud_filtered);
💡 参数说明:
setLeafSize(0.1, 0.1, 0.1)表示体素边长为 10 cm;- 数值越大,点云越稀疏,计算速度更快但细节损失更多;
- 常用范围为 0.05~0.2m。
1.4 效果对比
| 阶段 | 点云数量 | 特征保持 | 耗时 |
|---|---|---|---|
| 原始点云 | 120,000 | ✅ 完整 | ❌ 高 |
| 下采样后 | 35,000 | ✅ 形状保持 | ✅ 快速 |
结果:在保持主要结构形状的同时,点云数量减少约 70%,显著提升后续处理效率。
二、ROI 区域裁剪(Region of Interest Cropping)
2.1 目的
激光雷达扫描范围广,但我们通常只关心机器人周围一定区域 (如前方 10 米内)。
ROI 区域裁剪的目标是:
去除远距离、顶部、地面下方等无关区域,仅保留机器人周围感兴趣点云。
2.2 实现思路
- 使用 PassThrough Filter 对 x/y/z 轴设置范围;
- 或使用 CropBox Filter 定义一个三维包围盒裁剪点云。
2.3 核心代码
cpp
// 方法一:Z轴直通滤波,去掉地面以下点
pass.setInputCloud(cloud_in);
pass.setFilterFieldName("z");
pass.setFilterLimits(-1.5, 2.0);
pass.filter(*cloud_roi);
// 方法二:使用CropBox定义感兴趣区域
crop.setInputCloud(cloud_roi);
Eigen::Vector4f min_point(-10.0, -10.0, -0.5, 1.0);
Eigen::Vector4f max_point(10.0, 10.0, 1.0, 1.0);
crop.setMin(min_point);
crop.setMax(max_point);
crop.filter(*cloud_roi);
三、地面点云分割(Ground Segmentation)
3.1 目标与原理
在经过下采样与裁剪后,点云中仍包含大量地面点。
这些地面点若不去除,会被聚类算法错误地识别为障碍物。
因此,我们需要进行地面分割。
3.2 RANSAC 平面拟合法
RANSAC(随机采样一致性)是最常用的地面拟合方法。
其基本步骤:
- 随机选取若干点;
- 拟合平面模型;
- 判断其他点是否为内点;
- 选取内点数最多的模型作为地面平面。
3.3 核心代码
cpp
seg.setOptimizeCoefficients(true);
seg.setModelType(pcl::SACMODEL_PLANE);
seg.setMethodType(pcl::SAC_RANSAC); // 使用 RANSAC 随机采样一致性方法
seg.setMaxIterations(max_iterations); // 最大迭代次数
seg.setDistanceThreshold(distance_thresh); // 地面拟合容差
seg.setInputCloud(cloud_in);
seg.segment(*inliers, *coefficients); // 保存平面模型的参数 [a, b, c, d](即平面方程:ax + by + cz + d = 0)
// 提取地面与非地面点
extract.setInputCloud(cloud_in);
extract.setIndices(inliers); // 保存属于拟合平面的点索引
extract.setNegative(false);
extract.filter(*cloud_ground); // 提取地面点云
extract.setNegative(true);
extract.filter(*cloud_non_ground); // 提取非地面点云
四、总结
| 模块 | 主要作用 | 典型方法 | 特点 |
|---|---|---|---|
| 体素下采样 | 降低点云密度、提升实时性 | VoxelGrid | 结构保持好 |
| ROI 裁剪 | 去除远处与无关点 | CropBox/PassThrough | 减少冗余 |
| 地面分割 | 去除地面点,提高聚类精度 | RANSAC | 稳定可靠 |
经过这三个步骤,点云数据量减少超过 80%,同时保持几何结构完整性,为后续的目标检测、聚类与跟踪奠定坚实基础。