基于Win系统下PCL库入门到实践:IO模块之PCD文件的读写(附详细代码)

I/O(Input/Output) 是计算机系统里最基础的功能模块,负责数据的输入与输出。在 PCL 里,I/O 模块主要用于:点云数据的读写 (如 PCD、PLY、OBJ、PNG 等格式)、与其他系统交互 (ROS、OpenNI、RealSense、Velodyne 激光雷达等)、点云与图像的互相转换(如点云转 PNG,RGB-D 图像转点云)。

所有点云处理流程(滤波、分割、配准、重建等)都要从数据读取开始。IO 模块提供了统一的接口 ,**I/O 模块是点云处理的"桥梁",**没有 IO,就没有数据输入与结果输出,整个点云处理流程就无法闭环。

PCD文件读取

PCD文件的读取有两种,第一种是最基础的:实例化读取变量,调用read方法:

复制代码
pcl::PCDReader reader;
reader.read("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);

PCD文件的读取第二种:

复制代码
pcl::io::loadPCDFile("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);

直接调用loadPCDFile就可以读取了,再进这个函数的定义去看,其实就是用最基础的读取方式写的:

下面是读取并可视化的代码。

复制代码
#include <thread>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization//cloud_viewer.h>

using namespace std;

int main()
{
    pcl::PCLPointCloud2 Cloud;
    pcl::PCDReader reader;
    reader.read("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);
    //pcl::io::loadPCDFile("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);
    for(auto &f : Cloud.fields)cout <<f.name<<endl;

    PointCloud<PointXYZRGB >::Ptr Cloud2(new PointCloud<PointXYZRGB>);
    pcl::fromPCLPointCloud2(Cloud,*Cloud2);
    pcl::visualization::CloudViewer viewer("Viewer"); // 创建 CloudViewer
    viewer.showCloud(Cloud2);

    while (!viewer.wasStopped())// 保持显示
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    return 0;
}

这里定义为PCLPointCloud2的点的原因:

这里是不知道要读取得点云到底是什么格式得,PCLPointCloud2通用性强。无论是 PointXYZ、PointXYZRGB、PointXYZRGBA 还是自定义点,都能先读进来。后续在使用fromPCLPointCloud2函数去转换点的类型。

怎么知道该转换什么类型的点云数据:

复制代码
for(auto &f : Cloud.fields)cout <<f.name<<endl;

这一步就是在输出口打印其格式,fields 就是点云 每个点包含哪些字段 的列表

而 pcl::PCLPointField 结构大致是这样的:

复制代码
struct PCLPointField {
    std::string name;   // 字段名,比如 x,y,z,rgb,intensity等
    uint32_t offset;    // 在每个点的字节数据中的偏移量
    uint8_t datatype;   // 数据类型(FLOAT32, UINT32, UINT8 等)
    uint32_t count;     // 该字段包含多少个数(比如 x,y,z 都是 1;如果是 normal[3] 就是 3)
};

那么这样就直接可以打印出对应PCD文件的点云类型。后续直接定义相应类型的点。如结果图,打印字段为xyzrgb,定义PointXYZRGB就可以不丢失信息了。

复制代码
 PointCloud<PointXYZRGB >::Ptr Cloud2(new PointCloud<PointXYZRGB>);
 pcl::fromPCLPointCloud2(Cloud,*Cloud2);

这里就是定义指针类的点云,并用fromPCLPointCloud2将其转换给Cloud2,由于Cloud2定义为指针类型,而这个函数只接受值变量,所以直接给*Cloud2,同时也方便后面的可视化。

PCD文件保存

同样的保存也是两种方法:第一种就是

复制代码
pcl::PCDWriter writer;
writer.writeASCII("C:\\Users\\Desktop\\code\\pcl_ASCII.pcd",*Cloud2);

这里的write方法有多个,其实就是保存格式,上述的为ASCII格式,也可以是二进制格式,或者压缩二进制,如下所示:

复制代码
writer.write("C:\\Users\\Desktop\\code\\pcl_ASCII.pcd",*Cloud2);
writer.writeASCII("C:\\Users\\Desktop\\code\\pcl_ASCII.pcd",*Cloud2);
writer.writeBinary("C:\\Users\\Desktop\\code\\pcl_Binary.pcd",*Cloud2);
writer.writeBinaryCompressed("C:\\Users\\Desktop\\code\\pcl_Binary_zip.pcd",*Cloud2);

在上述的例程的基础上,显示结束后可以加上保存;发现保存成功了。在上述的例程的基础上,显示结束后可以加上保存;发现保存成功了。

第二种同样类似于读取,也是第一种封装的。

第二种的保存方式仍然是有多种格式的保存,如下:

复制代码
pcl::io::savePCDFile("C:\\Users\\Desktop\\code\\pcl.pcd",*Cloud2);
pcl::io::savePCDFileASCII("C:\\Users\\Desktop\\code\\pcl_Binary.pcd",*Cloud2);
pcl::io::savePCDFileBinary("C:\\Users\\Desktop\\code\\pcl_Binary.pcd",*Cloud2);
pcl::io::savePCDFileBinaryCompressed("C:\\Users\\Desktop\\code\\pcl_Binary_zip.pcd.pcd",*Cloud2);

完整代码:

复制代码
#include <thread>
#include <pcl/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/visualization//cloud_viewer.h>

using namespace std;

int main()
{

    pcl::PCLPointCloud2 Cloud;//这里是不知道要读取得点云到底是什么格式得,所以使用PCLPointCloud2可以读取更多得格式
#if 0
    pcl::PCDReader reader;
    reader.read("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);
#else
    pcl::io::loadPCDFile("C:\\Users\\admin\\Desktop\\code\\pcl_type.pcd", Cloud);
#endif
    for(auto &f : Cloud.fields)cout <<f.name<<endl;//这一步就是在输出口打印其格式

    pcl::PointCloud<pcl::PointXYZRGB >::Ptr Cloud2(new  pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::fromPCLPointCloud2(Cloud,*Cloud2);

    // 创建 CloudViewer
    pcl::visualization::CloudViewer viewer("Viewer");
    viewer.showCloud(Cloud2);

    // 保持显示
    while (!viewer.wasStopped())std::this_thread::sleep_for(std::chrono::milliseconds(100));
#if 0
    pcl::PCDWriter writer;
    writer.writeASCII("C:\\Users\\admin\\Desktop\\code\\pcl_ASCII.pcd",*Cloud2);
    writer.writeBinary("C:\\Users\\admin\\Desktop\\code\\pcl_Binary.pcd",*Cloud2);
    writer.writeBinaryCompressed("C:\\Users\\admin\\Desktop\\code\\pcl_Binary_zip.pcd",*Cloud2);
#else
    pcl::io::savePCDFileBinaryCompressed("C:\\Users\\admin\\Desktop\\code\\pcl_Binary_zip.pcd.pcd",*Cloud2);
    pcl::io::savePCDFileBinary("C:\\Users\\admin\\Desktop\\code\\pcl_Binary.pcd",*Cloud2);
    pcl::io::savePCDFile("C:\\Users\\admin\\Desktop\\code\\pcl.pcd",*Cloud2);
    pcl::io::savePCDFileASCII("C:\\Users\\admin\\Desktop\\code\\pcl.pcd",*Cloud2);
#endif


    return 0;
}
相关推荐
bkspiderx2 小时前
C++中的volatile:从原理到实践的全面解析
开发语言·c++·volatile
君义_noip3 小时前
信息学奥赛一本通 2134:【25CSPS提高组】道路修复 | 洛谷 P14362 [CSP-S 2025] 道路修复
c++·算法·图论·信息学奥赛·csp-s
liulilittle4 小时前
OPENPPP2 Code Analysis One
网络·c++·网络协议·信息与通信·通信
Morwit4 小时前
*【力扣hot100】 647. 回文子串
c++·算法·leetcode
天赐学c语言4 小时前
1.7 - 删除排序链表中的重要元素II && 哈希冲突常用解决冲突方法
数据结构·c++·链表·哈希算法·leecode
w陆压4 小时前
12.STL容器基础
c++·c++基础知识
龚礼鹏5 小时前
Android应用程序 c/c++ 崩溃排查流程二——AddressSanitizer工具使用
android·c语言·c++
qq_401700416 小时前
QT C++ 好看的连击动画组件
开发语言·c++·qt
额呃呃6 小时前
STL内存分配器
开发语言·c++
七点半7706 小时前
c++基本内容
开发语言·c++·算法