从PCD文件中读取与保存点云文件

        序列化和反序列化是将数据结构或对象转换为字节流(序列化)以及将字节流还原为数据结构或对象(反序列化)的过程。
        在计算机科学中,当我们需要将数据从内存中保存到磁盘或通过网络传输时,通常需要进行序列化操作。序列化将数据结构或对象转换为一个字节流的形式,以便能够进行持久化存储或传输。这样,在需要时就可以从字节流中还原出原始的数据结构或对象。
        反序列化则是将之前序列化过的字节流重新转换为原始的数据结构或对象,使其可以被系统再次使用。
        在点云领域中,序列化和反序列化操作允许我们将点云数据保存到文件中或通过网络传输,并在需要时重新加载点云数据。这对于点云处理、共享和传输非常有用。

        PCL(点云库)提供了一些函数来执行点云数据的序列化和反序列化操作,例如 pcl::io::savePCDFile()pcl::io::loadPCDFile()。这些函数将点云数据转换为二进制格式并保存到文件中,然后可以通过读取文件并解析字节流来还原点云数据。
        总结而言,序列化和反序列化操作是将数据结构或对象转换为字节流以及将字节流还原为原始数据结构或对象的过程,用于持久化存储、传输和再利用数据。

        字节流可以有多种不同的表现形式,其中包括二进制表示。
        二进制表示:字节流最常见的表现形式是二进制表示,即将数据转换为由 0 和 1 组成的位序列。在计算机系统中,所有的数据最终都以二进制形式存储和处理。
        文本表示:字节流也可以被解释为字符序列,具体的解释方式取决于所使用的字符编码。例如,在 ASCII 编码中,每个字节对应一个字符;而在 Unicode 编码中,每个字符可能需要多个字节进行表示。
        十六进制表示:为了方便可读性和显示,字节流经常以十六进制的形式进行表示。在十六进制表示中,每个字节用两个十六进制数字(0-9, A-F)表示。
        除了上述常见的表现形式,字节流还可以通过其他编码和压缩算法来进行表示,例如 Base64 编码、gzip 压缩等。
        在点云领域中,点云数据通常以二进制形式表示,因为它们包含大量的浮点数和坐标值,这些数据可以直接以二进制形式存储和处理。
        总结而言,字节流可以以多种不同的表现形式存在,包括二进制表示、文本表示和十六进制表示。具体的表现形式取决于数据的使用场景和编码方式。

        从文件中加载点云数据是反序列化的过程,而将点云保存到文件中是序列化的过程。具体而言:
        序列化:将数据结构或对象转换为字节流的过程。在点云库中,将点云数据转换为二进制形式,并将其写入磁盘文件,是一种序列化操作。这个过程将点云数据序列化为字节流并持久化存储到文件中。
        反序列化:将字节流还原为原始的数据结构或对象的过程。在点云库中,从磁盘文件中读取二进制数据,并将其解析为点云数据结构,是一种反序列化操作。这个过程将之前序列化的字节流反序列化为原始的点云数据。

反序列化:

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

int main(int argc, char** argv) {
    // 准备pcl::PointXYZ类型的点云
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    // 将pcd中的数据加载到cloud中
    if (pcl::io::loadPCDFile<pcl::PointXYZ>("../data/octants.pcd", *cloud) == -1) //* load the file
    {
        PCL_ERROR("Couldn't read file octants.pcd \n");
        return (-1);
    }

    std::cout << "Loaded "
        << cloud->width * cloud->height
        << " data points from octants.pcd with the following fields: "
        << std::endl;
    for (size_t i = 0; i < cloud->points.size(); ++i)
        std::cout << "     " << cloud->points[i].x
        << "  " << cloud->points[i].y
        << "  " << cloud->points[i].z << std::endl;

    return (0);
}

序列化:随机生成了5个点,并将之以ASCII形式保存(序列化)在test_pcd.pcd文件中

#include <pcl/visualization/cloud_viewer.h>
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

int main(int argc, char** argv) {
    pcl::PointCloud<pcl::PointXYZ> cloud;

    // Fill in the cloud data
    cloud.width = 5000;
    cloud.height = 1;
    cloud.is_dense = false; //该点云是非密集的
    cloud.points.resize(cloud.width * cloud.height);
    /*
    std::cout << rand() << std::endl;
    std::cout << rand() / (RAND_MAX + 1.0f) << std::endl;
    std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl;
    */
    // 随机生成5个点
    for (size_t i = 0; i < cloud.points.size(); ++i) {
        cloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
        cloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
    }

    pcl::io::savePCDFileASCII("../output_data/test_pcd.pcd", cloud);
    std::cerr << "Saved " << cloud.points.size() << " data points to test_pcd.pcd." << std::endl;
    /*
    for (size_t i = 0; i < cloud.points.size(); ++i)
        std::cerr << "    " << cloud.points[i].x << " " << cloud.points[i].y << " " << cloud.points[i].z << std::endl;
*/

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_show(new pcl::PointCloud<pcl::PointXYZ>);
    if (pcl::io::loadPCDFile("../output_data/test_pcd.pcd", *cloud_show) == -1) {
        PCL_ERROR("Couldn't read file  \n");
        return (-1);
    }
    else {
        pcl::visualization::CloudViewer viewer("simple cloud viewer");
        viewer.showCloud(cloud_show);
        while (!viewer.wasStopped())
        {
            // todo::
        }
    }

    return (0);
}

 输出的文件内容如下:

 有时为了节省空间,提高读写效率,还会以binary的格式进行序列化,即将save操作改为

pcl::io::savePCDFileBinary("../output_data/test_pcd_Binary.pcd", cloud);
pcl::io::savePCDFile("../output_data/test_pcd.pcd", cloud, true);

此时输出的内容如下:

ps:11行的DATA类型为binary,最后的内容由于是以二进制形式保存,故而不可以直接看到值,需要用程序读取。

输出文件大小对比:

 


         cloud.is_dense = false;是对点云数据结构中的 is_dense 属性进行设置。这个属性用于指示点云是否密集(dense)。
        当 is_dense 被设置为 false 时,表示点云是非密集的。这意味着点云中可能存在一些缺失或无效的点,例如由于传感器噪声、遮挡或其他原因导致的点云数据不完整。在非密集的点云中,某些点的位置信息可能会丢失或不准确。
        相反,当 is_dense 被设置为 true 时,表示点云是密集的。这意味着点云中的每个点都有有效和准确的位置信息。
        通过设置 cloud.is_dense = false;,你指示该点云是非密集的,即它可能包含缺失或无效的点。


std::cout << rand() << std::endl;
std::cout << rand() / (RAND_MAX + 1.0f) << std::endl;
std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl;

         这段代码使用了 C++ 的随机数生成函数 rand() 和输出流 std::cout,并进行了一些计算和打印操作。

  • std::cout << rand() << std::endl; 打印一个随机整数。rand() 函数会生成一个范围在 0 到 RAND_MAX 之间的整数,其中 RAND_MAX 是库定义的最大随机数值。该行代码将随机整数输出到标准输出流 std::cout 中,并通过 std::endl 进行换行。
  • std::cout << rand() / (RAND_MAX + 1.0f) << std::endl; 打印一个介于 0 和 1 之间的随机浮点数。这里使用 (RAND_MAX + 1.0f)RAND_MAX 转换为浮点数,然后用 rand() 除以该值来得到一个范围在 0 到 1 之间的随机浮点数。该行代码将随机浮点数输出到标准输出流中,并通过 std::endl 进行换行。

  • std::cout << 1024 * rand() / (RAND_MAX + 1.0f) << std::endl; 打印一个介于 0 和 1024 之间的随机整数。与上一行类似,这里先将 RAND_MAX 转换为浮点数,然后用 rand() 产生的随机数乘以 1024,再除以 (RAND_MAX + 1.0f) 来得到一个范围在 0 到 1024 之间的随机整数。该行代码将随机整数输出到标准输出流中,并通过 std::endl 进行换行。


#include <iostream> //标准c++库输入输出相关头文件
#include <pcl/io/pcd_io.h> // pcd读写相关头文件
#include <pcl/point_types.h> // pcl中支持的点类型头文件

// 定义点云格式,具体见下章
typedef pcl::PointXYZ PointT;

int main(int argc, char** argv)
{
	// 定义点云
	pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);

	// 读取点云,失败返回-1
	if (pcl::io::loadPCDFile<PointT>("../input_cloud/20230605_133316.pcd", *cloud) == -1)
	{
		PCL_ERROR("couldn't read file\n");
		return (-1);
	}

	// 输出点云大小 cloud->width * cloud->height
	std::cout << "点云大小:" << cloud->size() << std::endl;

	// 保存点云文件
	pcl::io::savePCDFile("../output_cloud/01_saveName_2.pcd", *cloud);

	system("pause"); // windows命令行窗口暂停
	return (0);
}

参考:02-点云输入/输出(I/O)

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值