一、常见点云数据格式
LAS/LAZ格式
LAS是点云数据的行业标准格式
LAZ是LAS的压缩版本
支持地理参考信息、颜色、强度等属性
PCD格式(Point Cloud Data)
PCL(Point Cloud Library)开发的格式
支持ASCII和二进制存储
包含头部信息和数据部分
PLY格式(Polygon File Format)
最初为存储3D扫描仪数据设计
支持点云和网格数据
可包含颜色、法线等属性
OBJ格式
简单文本格式
主要用于3D模型但也可存储点云
二、读写工具和库
PDAL(Point Data Abstraction Library)
开源点云数据处理库
支持多种格式转换和处理
PCL(Point Cloud Library)
强大的点云处理库
提供多种点云格式的读写接口
LASlib/LASzip
专门用于LAS/LAZ格式的读写
CloudCompare
开源点云处理软件
支持多种格式的导入导出
三、PCL读写点云数据
PCL(Point Cloud Library)是处理点云数据的强大开源库,提供了多种点云数据格式的读写功能。以下是使用PCL进行点云数据读写的主要方法。
1. 基本点云数据结构
pcl::PointCloud 类
主要属性:
width
- 点云的宽度(对于无组织点云表示点数,对于有组织点云表示每行点数)height
- 点云的高度(对于无组织点云通常为1,对于有组织点云表示行数)points
- 存储所有点的向量is_dense
- 布尔值,表示点云是否包含无限/NaN值sensor_origin_
- 传感器原点坐标(Eigen::Vector4f)sensor_orientation_
- 传感器方向(Eigen::Quaternionf)
2. 常用点类型
点类型 | 描述 | 包含数据 |
---|---|---|
pcl::PointXYZ |
基本XYZ点 | float x, y, z |
pcl::PointXYZI |
带强度的XYZ点 | float x, y, z, intensity |
pcl::PointXYZRGB |
带RGB颜色的XYZ点 | float x, y, z; uint32_t rgb |
pcl::PointXYZRGBA |
带RGBA颜色的XYZ点 | float x, y, z; uint32_t rgba |
pcl::PointNormal |
带法线的XYZ点 | float x, y, z, normal_x, normal_y, normal_z, curvature |
3. 读写点云数据方法
读取点云文件
cpp
#include <pcl/io/pcd_io.h>
// 读取PCD文件
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("input.pcd", *cloud) == -1) {
PCL_ERROR("Couldn't read file input.pcd\n");
return -1;
}
// 读取PLY文件
#include <pcl/io/ply_io.h>
pcl::PLYReader reader;
reader.read("input.ply", *cloud);
写入点云文件
cpp
// 写入PCD文件(二进制格式)
pcl::io::savePCDFileBinary("output.pcd", *cloud);
// 写入PCD文件(ASCII格式)
pcl::io::savePCDFileASCII("output_ascii.pcd", *cloud);
// 写入PLY文件
pcl::PLYWriter writer;
writer.write("output.ply", *cloud, false); // false表示不保存二进制格式
4. 常用方法参数表
方法 | 参数 | 返回值 | 描述 |
---|---|---|---|
loadPCDFile |
(const std::string &file_name, PointCloud &cloud) |
int |
加载PCD文件 |
savePCDFile |
(const std::string &file_name, const PointCloud &cloud, bool binary_mode=false) |
int |
保存PCD文件 |
loadPLYFile |
(const std::string &file_name, PointCloud &cloud) |
int |
加载PLY文件 |
savePLYFile |
(const std::string &file_name, const PointCloud &cloud, bool binary_mode=false) |
int |
保存PLY文件 |
fromROSMsg |
(const sensor_msgs::PointCloud2 &msg, PointCloud &cloud) |
void |
从ROS消息转换 |
toROSMsg |
(const PointCloud &cloud, sensor_msgs::PointCloud2 &msg) |
void |
转换为ROS消息 |
其他格式支持
1. PLY格式读写
cpp
#include <pcl/io/ply_io.h>
// 读取PLY文件
pcl::PLYReader reader;
reader.read("input.ply", *cloud);
// 写入PLY文件
pcl::PLYWriter writer;
writer.write("output.ply", *cloud);
2. OBJ格式读写
cpp
#include <pcl/io/obj_io.h>
// 读取OBJ文件
pcl::OBJReader reader;
reader.read("input.obj", *cloud);
// 写入OBJ文件
pcl::OBJWriter writer;
writer.write("output.obj", *cloud);
二进制与ASCII格式
PCD文件可以保存为二进制或ASCII格式:
cpp
// 保存为二进制格式(更小更快)
pcl::io::savePCDFileBinary("output_binary.pcd", *cloud);
// 保存为压缩二进制格式(更小)
pcl::io::savePCDFileBinaryCompressed("output_compressed.pcd", *cloud);
// 保存为ASCII格式(可读)
pcl::io::savePCDFileASCII("output_ascii.pcd", *cloud);
5. 点云基本操作
添加点
cpp
pcl::PointXYZ point;
point.x = 1.0; point.y = 2.0; point.z = 3.0;
cloud->points.push_back(point);
访问点
cpp
// 随机访问
float x = cloud->points[10].x;
// 遍历所有点
for (const auto& point : *cloud) {
std::cout << "x: " << point.x
<< " y: " << point.y
<< " z: " << point.z << std::endl;
}
点云属性
cpp
std::cout << "点云大小: " << cloud->size() << std::endl;
std::cout << "宽度: " << cloud->width << std::endl;
std::cout << "高度: " << cloud->height << std::endl;
std::cout << "是否为有组织点云: " << cloud->isOrganized() << std::endl;
6. 常用信号(ROS相关)
在PCL与ROS结合使用时,常用的信号包括:
信号 | 参数 | 描述 |
---|---|---|
pcl::visualization::PointPickingEvent |
const pcl::visualization::PointPickingEvent &event |
当用户选择点时触发 |
pcl::visualization::KeyboardEvent |
const pcl::visualization::KeyboardEvent &event |
键盘事件 |
pcl::visualization::MouseEvent |
const pcl::visualization::MouseEvent &event |
鼠标事件 |
7. 示例代码:完整读写流程
cpp
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int main() {
// 创建一个点云对象
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
// 填充点云数据
cloud->width = 5;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
for (auto& point : *cloud) {
point.x = 1024 * rand() / (RAND_MAX + 1.0f);
point.y = 1024 * rand() / (RAND_MAX + 1.0f);
point.z = 1024 * rand() / (RAND_MAX + 1.0f);
}
// 保存到文件
pcl::io::savePCDFileASCII("test_pcd.pcd", *cloud);
std::cout << "保存了 " << cloud->size() << " 个点到 test_pcd.pcd" << std::endl;
// 从文件读取
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_from_file(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile<pcl::PointXYZ>("test_pcd.pcd", *cloud_from_file);
// 显示读取的点云
for (const auto& point : *cloud_from_file)
std::cout << " " << point.x << " " << point.y << " " << point.z << std::endl;
return 0;
}
8. 注意事项
内存管理:使用智能指针(如
boost::shared_ptr
或pcl::PointCloud::Ptr
)管理点云对象文件格式:PCD文件有ASCII和二进制格式,二进制格式更节省空间
点云类型:读写时要确保点云类型匹配
ROS集成:PCL与ROS紧密集成,可以方便地与
sensor_msgs::PointCloud2
相互转换