PCL:カスタムポイントタイプ(PCLの既存のフィールドをマージ|新しいフィールドを追加)

1点群タイプをカスタマイズする理由

PCLには、XYZデータから、PFH(Point Feature Histogram)などのより複雑なn次元ヒストグラム表現まで、さまざまな事前定義されたポイントタイプが付属しています。考えられるすべてのケースをカバーするために、PCLは多数のポイントタイプを定義します。完全なリストについては、 point_types.hppを参照してください

ただし、場合によっては、ユーザーは自分のニーズを満たすために新しいタイプを定義したいと思うでしょう。

たとえば、PCLはとを提供しますPoint XYZIPointXYZRGB、座標、色、強度を同時に含むポイントタイプは提供しません。別の例では、PCLはGPSTimeを含むポイントタイプを提供しません。

ここでは、PCLがポイントタイプをカスタマイズする方法を示します。実際のニーズに応じて、PCLの既存のポイントタイプを組み合わせたり(とマージ)、新しいフィールド()を新しいポイントタイプ()としてカスタマイズしたりできます。PointXYZIPointXYZRGBPointXYZRGBIGPSTimePointXYZRGBIGpsTime

2点群タイプをカスタマイズする方法

2.1既存のフィールドをマージします(例としてPointXYZRGBIを取り上げます)

説明:例として、マージを取り、新しいポイントタイプを定義XYZますRGBIntensityPointXYZRGBI

コード:

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

結果は次のことを示しています。

ここに画像の説明を挿入

図1点群表示

ここに画像の説明を挿入

図2PointXYZRGBI.pcdファイルヘッダー

知らせ:

  • マージされたフィールドに値を割り当てることができ、割り当てられたポイントクラウドを正常に表示して、カスタムポイントタイプが成功したことを示すことができます!
  • 実際のニーズに応じて、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;
}

結果は次のことを示しています。
ここに画像の説明を挿入

図1点群表示

ここに画像の説明を挿入

図2PointXYZRGBGpsTime.pcdファイルヘッダー

知らせ:

  • 新しいフィールドに値を割り当てることができ、割り当てられた点群を正常に表示して、カスタムポイントタイプが成功したことを示すことができます!
  • 実際のニーズに応じて、任意のフィールドを定義して新しいポイントタイプを作成できます。
  • ポイントタイプマクロを登録するときは、追加されたすべてのフィールドを含める必要があります。そうしないと、未登録のフィールドを通常は使用できません。

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

おすすめ

転載: blog.csdn.net/weixin_46098577/article/details/122331796