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;
}