第2章:点云数据结构 — PCL中的PointCloud核心字段与组织方式
说实话,刚接触PCL那会儿,我对着PointCloud
今天咱们就把它彻底掰开揉碎。你想想看,点云说白了就是一堆三维点的集合。但怎么组织这些点,PCL给出了两种方式:有序和无序。这两种方式直接决定了你后续处理算法的选择。
2.1 PointCloud的核心字段
先看一个典型的点云对象长什么样:
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud.points; // 存储所有点的容器
cloud.width; // 宽度
cloud.height; // 高度
cloud.is_dense; // 是否稠密
cloud.sensor_origin_; // 传感器原点
cloud.sensor_orientation_; // 传感器朝向
这几个字段,我一个个说。
2.1.1 points — 灵魂所在
这是点云数据的本体。一个std::vector<T>,里面装着所有点。每个点可以是PointXYZ(只有xyz)、PointXYZRGB(带颜色)、PointNormal(带法向量)等等。我个人习惯用PointXYZRGB,因为调试时能看到颜色,方便定位问题。
2.1.2 width 和 height — 组织方式的开关
这两个字段决定了点云是有序还是无序。规则很简单:
- 无序点云:height = 1,width = 点的总数
- 有序点云:height > 1,width = 每行点数,总点数 = width * height
我在项目中遇到过有人把有序点云当成无序处理,结果滤波算法跑出来的结果完全不对。嗯,这里要注意:有序点云的行列关系一旦被破坏,你就再也恢复不了原始的空间结构了。
2.1.3 is_dense — 坑点预警
这个字段表示点云中是否包含无效点(比如NaN或Inf)。true表示所有点都有效,false表示存在无效点。我曾经在读取Kinect数据时,没检查is_dense就直接做滤波,结果程序崩溃了。后来养成习惯:处理前先调用cloud.is_dense检查,必要时用pcl::removeNaNFromPointCloud清理一下。
2.2 有序点云 vs 无序点云
说白了,有序点云就像一张深度图,每个像素对应一个三维点。无序点云就是一锅粥,点与点之间没有空间邻居关系。
2.2.1 有序点云
通常来自RGB-D相机(如Kinect、RealSense)或激光雷达的扫描线数据。它的好处是:
- 天然支持邻域搜索(直接通过行列索引找邻居)
- 可以结合图像处理算法(比如用OpenCV处理深度图)
- 滤波效率高,因为不需要构建KD-Tree
举个例子,从有序点云中取某个点的上下左右邻居:
// 假设cloud是有序点云,width=640, height=480
int row = 200, col = 300;
int idx = row * cloud.width + col;
// 左邻居
pcl::PointXYZ left = cloud.points[idx - 1];
// 右邻居
pcl::PointXYZ right = cloud.points[idx + 1];
// 上邻居
pcl::PointXYZ up = cloud.points[idx - cloud.width];
// 下邻居
pcl::PointXYZ down = cloud.points[idx + cloud.width];
你看,多直接。但要注意边界检查,我刚开始写的时候没注意,程序跑着跑着就崩了。
2.2.2 无序点云
这是更常见的情况。激光雷达扫描一圈,或者多帧拼接后的点云,基本都是无序的。它的特点是:
- 点与点之间没有空间顺序
- 要搜索邻居必须构建KD-Tree或Octree
- 滤波算法更通用,但计算开销更大
std::cout << "height: " << cloud.height << std::endl;,一目了然。
2.3 核心逻辑结构图
下面这张图帮你理清PointCloud
2.4 实际项目中的选择建议
我做了这么多年点云处理,总结了几条经验:
| 场景 | 推荐组织方式 | 原因 |
|---|---|---|
| RGB-D相机实时处理 | 有序点云 | 利用行列关系加速邻域搜索,滤波效率高 |
| 激光雷达多帧拼接 | 无序点云 | 点云密度不均匀,有序结构无意义 |
| SLAM建图后的全局地图 | 无序点云 | 多帧融合后行列关系已丢失 |
| 需要快速体素滤波 | 无序点云 | 体素滤波不依赖点云顺序 |
核心要点:有序点云是「有结构的宝藏」,无序点云是「散落的珍珠」。前者适合快速邻域操作,后者更通用灵活。选择哪种,取决于你的传感器和算法需求。
最后说一句,别被这些概念吓到。你只要记住:height=1就是无序,height>1就是有序。剩下的,用多了自然就熟了。
可可精品资料库