一、常見點云數據格式
-
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
相互轉換