PCL点云之旅03-PCL点的类型

429 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

PointT类型

PCL的PointT类型可以追溯到它在ROS作为开源库被开发的时候,大家一致认为,点云是复杂的n维度结构,它应该能够传递不同类型的信息,然而用户应该知道并且理解需要传送什么信息,然而用户应该知道并且理解需要传送什么样的信息,从而使代码更加易于调试和优化等。下面给出一个例子,是对XYZ数据的简单操作。对带有SSE功能的处理器,最高效的方法就是存储三维坐标为浮点数。然后紧跟一个浮点型数据作为填补位数满足其存储对其要求。

strcut PointXYZ{
    float x;
    float y;
    float z;
    float padding;
}

然而,当用户在嵌入式平台上寻找编译PCL的时候,增加额外的填补就是浪费存储空间。因此,你可以使用一个简单的不带最后浮点数的PointXYZ结构来替代。此外,如果你的应用程序需要一个包含XYZ的三维数据,RGB信息和每个点的估计法线的PointXYZRGBNormal类型,定义包含以上所有内容的结构是简单的。不需要做其他的更改,从而增加了代码的重用性和可读性。

PCL中有哪些可用的PointT类型

为了涵盖能够想到的所有可能情况,PCL中定义了大量的point类型。下面是一小段。在point_types.hpp中有完整的目录,这个列表很重要,因为在你自己的类型之前,需要了解已有的类型。如果你需要的数据已经存在于PCL,那么就不需要重复定义了。

PointXYZ-成员变量: float x,y,z;

PointXYZ是使用最常见的一个点数据类型,因为他只包含三维坐标XYZ坐标信息,这三个浮点数加一个浮点数来满足存储对其。用户可以利用points[i].data[0],或者points[i].x来访问点的x坐标值。

union{
float data[4];
struct
{
float x;
float y;
float z;
};
};

PointXYZI-成员变量:float x,y,z,intensity;

PointXYZI是一个简单的XYZ坐标加上intensity的point类型。理想情况下,这四个变量将新建一个单独的结构体。并且满足存储对齐,然而,由于point的大部分操作会吧data[4]元素设置成0或者1(用于变换),不能让intensity和xyz在同一个结构体中。如果这样的话其内容会被覆盖。例如:两个点的点积会吧他们的第四个元素设置成0,否则该点积没有意义。诸如此类。因此,对于存储内容对其。用三个额外的浮点数来填补in-tensity,这样在存储方面效率较低。但是符合存储对齐要求。运行效率较高。

union
{
float data[4];
struct
{
float x;
float y;
float z;
};
};
union
{
struct
{
float intensity;
};
float data_c[4];
}

实际案例

点云生成

实现效果

]_J{XCQ$7M~P4S0{0R}3V.png

步骤讲解

  • 首先新建一个空白的Cpp项目,然后配置项目属性。【属性配置方式看这篇文章:juejin.cn/post/713238…
  • 导入pcl依赖库,由于我们的类型点都是在pcl_types下面的,所以我们需要导入pcl_types这个头文件。又由于我们需要将点云文件保存成pcd文件,所以我们需要导入pcl_io头文件。
  • 这里我们设置点的宽度,也就是width属性,它能够确定无序点云中点的个数,能够确定有序点云中点的宽度
  • 然后我们设置点云的height属性,如果height为1,那么就是无序点云。否则他就是代表有序点云的高度
  • 规定我们的点云中有多少个点,通过resize方法。
  • 最后通过savePCDFileASCII来保存点云模型。
  • 运行程序,最后用cloudcompare预览生成的点云模型

代码实现

#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
int main() {
	pcl::PointCloud<pcl::PointXYZ> cloud;
	cloud.width = 5;
	cloud.height = 1;
	cloud.is_dense = true;
	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);
	for (const auto &point : cloud)
		std::cerr << point.x << point.y << point.z << std::endl;
	system("pause");
	return (0);
}

扩展思考 要是我们想给点云上色,那该怎么办? 其实很简单,我们只要使用PointXYZGRB这个点材质就可以了。

int main() {
	pcl::PointCloud<pcl::PointXYZRGB> cloud;
	cloud.width = 10000;
	cloud.height = 1;
	cloud.is_dense = true;
	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);
		point.rgb = 0xff00ff;
	}
	pcl::io::savePCDFileASCII("test_pcd.pcd", cloud);
	for (const auto &point : cloud)
		std::cerr << point.x << point.y << point.z << std::endl;
	system("pause");
	return (0);
}

效果

image.png

【PCL点云之旅03-PCL点的类型】 到此结束,如果您觉得对您有帮助的话,可以点赞收藏一下哦。您的支持就是对我最大的鼓励,能让我得到更多的推送流量,帮助到更多的人,最后感谢您花费宝贵的时间认真的阅读这篇文章。如果说您有什么需要我改进的建议欢迎到评论区一起和我讨论❤❤❤