2. 点云数据结构:PCL点云类型、XYZ、XYZRGB、PointXYZI
点云数据长什么样?说白了,就是一堆三维空间里的点。每个点带着自己的坐标 (x, y, z),有时候还带着颜色、强度之类的附加信息。PCL(Point Cloud Library)把这些点组织成了不同的结构体,也就是我们今天要聊的点云类型。
我个人习惯把点云类型比作「集装箱」。不同类型的集装箱,装的货不一样。有的只装坐标,有的还装颜色,有的装反射强度。你选哪种,取决于你的传感器和算法需求。
2.1 最基础的点:pcl::PointXYZ
这是最常用的点类型。它只包含三个浮点数:x、y、z。没有别的了。简单、纯粹、省内存。
我在项目中遇到过一个问题:用 Velodyne 激光雷达采集数据,默认输出就是 XYZ 格式。如果你只需要做几何处理(比如体素滤波、平面分割),用这个类型就够了。没必要加载颜色信息,白白浪费带宽和内存。
// 定义一个 XYZ 点
pcl::PointXYZ point;
point.x = 1.23f;
point.y = 4.56f;
point.z = 7.89f;
// 定义点云
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud.push_back(point);
2.2 带颜色的点:pcl::PointXYZRGB
这个类型在 XYZ 的基础上,加了一个 RGB 字段。注意,这里的 RGB 是打包在一个 32 位整数里的。每个颜色通道占 8 位,顺序是 BGR(不是 RGB,容易搞混)。
为什么会这样?嗯,这跟 PCL 底层用的 RGB 编码方式有关。你赋值的时候,最好用现成的函数,别自己手动拼。
pcl::PointXYZRGB point;
point.x = 1.0f;
point.y = 2.0f;
point.z = 3.0f;
// 正确赋值方式
uint8_t r = 255, g = 128, b = 64;
uint32_t rgb = (static_cast<uint32_t>(r) << 16 |
static_cast<uint32_t>(g) << 8 |
static_cast<uint32_t>(b));
point.rgb = *reinterpret_cast<float*>(&rgb);
// 或者用 PCL 提供的工具函数
point.rgb = pcl::RGB(255, 128, 64).rgba;
PointXYZRGB 常用于 RGB-D 相机(比如 Kinect、RealSense)或者多传感器融合场景。颜色信息对语义分割、目标识别很有帮助。但注意,如果你只是做几何配准,颜色反而可能引入噪声。
2.3 带强度的点:pcl::PointXYZI
这个类型在 XYZ 的基础上,加了一个 intensity 字段。强度值通常表示激光雷达回波的反射强度。不同材质的物体,反射强度不一样。比如,路面的强度通常比树叶低。
我记得有一次做地面分割,单纯用高度信息效果不好。后来加了强度阈值,把低强度的点(比如沥青路面)和高强度的点(比如白色车道线)分开处理,效果立竿见影。
pcl::PointXYZI point;
point.x = 0.0f;
point.y = 0.0f;
point.z = 0.0f;
point.intensity = 150.0f; // 强度值范围通常 0-255
2.4 其他常见点类型
除了上面三种,PCL 还提供了很多变体。我列个表,方便你快速查阅:
| 点类型 | 字段 | 典型用途 |
|---|---|---|
| PointXYZ | x, y, z | 纯几何处理 |
| PointXYZRGB | x, y, z, rgb | RGB-D 相机、语义分割 |
| PointXYZI | x, y, z, intensity | 激光雷达、强度滤波 |
| PointXYZRGBA | x, y, z, rgb, alpha | 带透明度的彩色点云 |
| PointXYZRGBL | x, y, z, rgb, label | 语义标注数据 |
| PointNormal | x, y, z, normal_x, normal_y, normal_z, curvature | 法线估计、曲面重建 |
你想想看,实际项目中,我们经常需要把不同传感器的数据融合到一起。比如,激光雷达给 XYZI,相机给 RGB。这时候,你就得把数据转成统一的点类型。我个人习惯用 PointXYZRGB,把强度映射成灰度颜色,或者用 PointXYZRGBL 保存语义标签。
2.5 点云数据结构的核心逻辑
下面这张图,是我自己总结的点云类型选择逻辑。你可以把它当作一个决策树:
说白了,选点类型就是选数据结构。选对了,代码简洁、运行快。选错了,要么浪费内存,要么丢失关键信息。我个人建议:
- 纯激光雷达几何处理:用 PointXYZ,别犹豫。
- 需要强度信息:用 PointXYZI,比如做地面分割、路沿检测。
- 融合相机数据:用 PointXYZRGB,颜色对目标识别帮助很大。
- 做语义标注:用 PointXYZRGBL,标签字段能省去很多数据管理的麻烦。
嗯,关于点云数据结构,今天就聊这么多。你只要记住:点云类型就是数据的「容器」,选对容器,事半功倍。