PCL:自定义点类型(合并PCL已有字段 | 添加新的字段)
Posted 没事就要敲代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PCL:自定义点类型(合并PCL已有字段 | 添加新的字段)相关的知识,希望对你有一定的参考价值。
1 为什么要自定义点云类型
PCL 附带了各种预定义的点类型,从 XYZ 数据到更复杂的 n 维直方图表示,如 PFH(点特征直方图)。为了涵盖我们可以想到的所有可能的情况,PCL定义了大量的点类型。有关完整列表,请参阅point_types.hpp。
但是,在某些情况下,用户希望定义新类型,来满足自身的需求。
比如,PCL提供了Point XYZI
和PointXYZRGB
,却没有提供同时包含坐标、颜色和强度的点类型;又比如,PCL没有提供有包含GPSTime
的点类型。
这里,给出PCL自定义点类型的方法,可以根据实际需要,合并PCL已有的点类型(将PointXYZI
与 PointXYZRGB
合并为 PointXYZRGBI
),或者自定义新的字段(GPSTime
)作为新的点类型(PointXYZRGBIGpsTime
)
2 自定义点云类型的方法
2.1 合并已有的字段(以PointXYZRGBI为例)
描述:以合并XYZ
,RGB
,Intensity
为例,定义新的点类型 PointXYZRGBI
代码:
#include <pcl/io/pcd_io.h>
//-------------------------- 自定义点云类型 --------------------------
struct PointXYZRGBIGpsTime
PCL_ADD_POINT4D; //添加XYZ,此时相当于 PointXYZ
PCL_ADD_RGB; //添加RGB,此时相当于 PointXYZRGB
PCL_ADD_INTENSITY; //添加Intensity,此时相当于 PointXYZRGBI
EIGEN_MAKE_ALIGNED_OPERATOR_NEW //确保new操作符对齐操作
EIGEN_ALIGN16;//强制SSE内存对齐
//注册点类型宏(要包含所有添加的字段,否则无法正常使用未注册的字段)
POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBIGpsTime,
(float, x, x)
(float, y, y)
(float, z, z)
(uint8_t, b, b)
(uint8_t, g, g)
(uint8_t, r, r)
(float, rgb, rgb)
(float, intensity, intensity)
)
//========================== 自定义点云类型 ==========================
using namespace std;
typedef PointXYZRGBIGpsTime PointT;
//测试函数
void test_XYZRGBI()
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
cloud->width = 1000;
cloud->height = 1;
cloud->is_dense = true;
cloud->points.resize(cloud->width*cloud->height);
for (size_t i = 0; i < cloud->points.size(); i++)
///XYZ
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);
///RGB
cloud->points[i].r = (uint8_t)(i * 255 / cloud->points.size());
cloud->points[i].g = (uint8_t)((cloud->points.size() - i) * 255 / cloud->points.size());
cloud->points[i].b = (uint8_t)(i * 255 / cloud->points.size());
///Intensity
cloud->points[i].intensity = i;
pcl::io::savePCDFileBinary("PointXYZRGBI.pcd", *cloud);
int main()
test_XYZRGBI();
return 0;
结果展示:
注意:
- 可以给合并的字段赋值,并且能够成功显示赋值后的点云,说明自定义点类型成功!
- 可根据实际需要,合并任意PCL中已有的任意字段,构造出新的点类型。
- 注册点类型宏时,要包含所有添加的字段,否则无法正常使用未注册的字段。
2.2 添加新的字段(以GpsTime为例)
描述:合并XYZ和RGB,并定义新的字段 GpsTime
代码:
#include <pcl/io/pcd_io.h>
//-------------------------- 自定义点云类型 --------------------------
struct PointXYZRGBGpsTime
PCL_ADD_POINT4D; //添加XYZ,此时相当于 PointXYZ
PCL_ADD_RGB; //添加RGB,此时相当于 PointXYZRGB
double GpsTime; //添加新的字段
EIGEN_MAKE_ALIGNED_OPERATOR_NEW //确保new操作符对齐操作
EIGEN_ALIGN16;//强制SSE内存对齐
//注册点类型宏(要包含所有添加的字段,否则无法正常使用未注册的字段)
POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBGpsTime,
(float, x, x)
(float, y, y)
(float, z, z)
(uint8_t, b, b)
(uint8_t, g, g)
(uint8_t, r, r)
(float, rgb, rgb)
(double, GpsTime, GpsTime)
)
//========================== 自定义点云类型 ==========================
using namespace std;
typedef PointXYZRGBGpsTime PointT;
//测试函数
void test_XYZRGBGpsTime()
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
cloud->width = 1000;
cloud->height = 1;
cloud->is_dense = true;
cloud->points.resize(cloud->width*cloud->height);
for (size_t i = 0; i < cloud->points.size(); i++)
///XYZ
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);
///RGB
cloud->points[i].r = (uint8_t)(i * 255 / cloud->points.size());
cloud->points[i].g = (uint8_t)((cloud->points.size() - i) * 255 / cloud->points.size());
cloud->points[i].b = (uint8_t)(i * 255 / cloud->points.size());
///GpsTime
cloud->points[i].GpsTime = i * 1.0;
pcl::io::savePCDFileBinary("PointXYZRGBGpsTime.pcd", *cloud);
int main()
test_XYZRGBGpsTime();
return 0;
结果展示:
注意:
- 可以给新的字段赋值,并且能够成功显示赋值后的点云,说明自定义点类型成功!
- 可根据实际需要,定义任意字段,构造出新的点类型。
- 注册点类型宏时,要包含所有添加的字段,否则无法正常使用未注册的字段。
3 自定义点类型调用PCL模板类
从 PCL-1.7 开始,如果希望新的点类型和PCL提供的点类型那样,能够使用 PCL 中特定的模板类或者模板函数,需要先定义PCL_NO_PRECOMPILE
,然后再包含任何 PCL 头文件以包含模板化算法。需要在所有头文件之前添加以下代码:
#define PCL_NO_PRECOMPILE
描述:以新的点类型调用PCL的体素下采样模板类为例。
代码:
#define PCL_NO_PRECOMPILE //如果想使用PCL提供的模板类,比如体素下采样,需要添加此行代码。若不添加,生成代码时回报错。
#include <pcl/io/pcd_io.h>
#include<pcl/io/pcd_io.h>
#include<pcl/filters/voxel_grid.h>
//-------------------------- 自定义点云类型 --------------------------
struct PointXYZRGBGpsTime
PCL_ADD_POINT4D; //添加XYZ,此时相当于 PointXYZ
PCL_ADD_RGB; //添加RGB,此时相当于 PointXYZRGB
double GpsTime; //添加新的字段
EIGEN_MAKE_ALIGNED_OPERATOR_NEW //确保new操作符对齐操作
EIGEN_ALIGN16;//强制SSE内存对齐
//注册点类型宏(要包含所有添加的字段,否则无法正常使用未注册的字段)
POINT_CLOUD_REGISTER_POINT_STRUCT(PointXYZRGBGpsTime,
(float, x, x)
(float, y, y)
(float, z, z)
(uint8_t, b, b)
(uint8_t, g, g)
(uint8_t, r, r)
(float, rgb, rgb)
(double, GpsTime, GpsTime)
)
//========================== 自定义点云类型 ==========================
using namespace std;
typedef PointXYZRGBGpsTime PointT;
void test_XYZRGBGpsTime_sub()
//----------------------------- 点云填充 -----------------------------
pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);
cloud->width = 1000;
cloud->height = 1;
cloud->is_dense = true;
cloud->points.resize(cloud->width*cloud->height);
for (size_t i = 0; i < cloud->points.size(); i++)
///XYZ
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);
///RGB
cloud->points[i].r = (uint8_t)(i * 255 / cloud->points.size());
cloud->points[i].g = (uint8_t)((cloud->points.size() - i) * 255 / cloud->points.size());
cloud->points[i].b = (uint8_t)(i * 255 / cloud->points.size());
///GpsTime
cloud->points[i].GpsTime = i * 1.0;
pcl::io::savePCDFileBinary("PointXYZRGBGpsTime.pcd", *cloud);
//============================= 点云填充 ==============================
//---------------------------- 体素下采样 -----------------------------
pcl::VoxelGrid<PointT>vg;
vg.setInputCloud(cloud);
vg.setLeafSize(100, 100, 100);
pcl::PointCloud<PointT>::Ptr cloud_sub(new pcl::PointCloud<PointT>);
vg.filter(*cloud_sub);
pcl::io::savePCDFileBinary("PointXYZRGBGpsTime_sub.pcd", *cloud_sub);
//============================ 体素下采样 =============================
int main()
test_XYZRGBGpsTime_sub();
return 0;
结果展示:
参考链接:https://pcl.readthedocs.io/projects/tutorials/en/master/adding_custom_ptype.html#adding-custom-ptype
以上是关于PCL:自定义点类型(合并PCL已有字段 | 添加新的字段)的主要内容,如果未能解决你的问题,请参考以下文章