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

2023-11-21 04:40
文章标签 读取 保存 点云 pcd

本文主要是介绍从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 datacloud.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>);// 读取点云,失败返回-1if (pcl::io::loadPCDFile<PointT>("../input_cloud/20230605_133316.pcd", *cloud) == -1){PCL_ERROR("couldn't read file\n");return (-1);}// 输出点云大小 cloud->width * cloud->heightstd::cout << "点云大小:" << cloud->size() << std::endl;// 保存点云文件pcl::io::savePCDFile("../output_cloud/01_saveName_2.pcd", *cloud);system("pause"); // windows命令行窗口暂停return (0);
}

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

这篇关于从PCD文件中读取与保存点云文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/Scarlett2025/article/details/131400678
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/399865

相关文章

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

C#实现SHP文件读取与地图显示的完整教程

《C#实现SHP文件读取与地图显示的完整教程》在地理信息系统(GIS)开发中,SHP文件是一种常见的矢量数据格式,本文将详细介绍如何使用C#读取SHP文件并实现地图显示功能,包括坐标转换、图形渲染、平... 目录概述功能特点核心代码解析1. 文件读取与初始化2. 坐标转换3. 图形绘制4. 地图交互功能缩放

java读取excel文件为base64实现方式

《java读取excel文件为base64实现方式》文章介绍使用ApachePOI和EasyExcel处理Excel文件并转换为Base64的方法,强调EasyExcel适合大文件且内存占用低,需注意... 目录使用 Apache POI 读取 Excel 并转换为 Base64使用 EasyExcel 处

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.