記事ディレクトリ
1点群タイプをカスタマイズする理由
PCLには、XYZデータから、PFH(Point Feature Histogram)などのより複雑なn次元ヒストグラム表現まで、さまざまな事前定義されたポイントタイプが付属しています。考えられるすべてのケースをカバーするために、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;
}
結果は次のことを示しています。