PCL 学习(2)——基本数据类型与点云数据拼接

点云数据分为有序与无序两种类型:

HEIGHT被设置为1,可以用来作为判断是有序点云或无序点云的判断标准。

接下来介绍几种常用的点云类型:

1、PointXYZ

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

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

2、PointXYZI

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

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

3、PointXYZRGB 

     rgb信息被包含在一个浮点型变量中。rgb数据被压缩到一个浮点数里的原因在于早期PCL是作为ROS项目的一部分来开发的,那里RGB数据是用浮点数来传送的。

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

访问方式(注意访问方式有两种,“cloud->”和“cloud.”这两种访问方式主要取决于你如何定义点云对象,如下代码所示,采用哪种对象定义方式,就选择对应的访问符号):

pcl::PointCloud<pcl::PointXYZ> ::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
cloud->points[i].x = 1;
cloud->points[i].y = 2;
cloud->points[i].z = 3;
int r = cloud->points[i].r;
int g = cloud->points[i].g;
int b = cloud->points[i].b;
cloud->points[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud->points[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud->points[i].normal[2] = 1024 * rand () / (RAND_MAX + 1.0f);

//
pcl::PointCloud<pcl::PointXYZ> cloud
cloud.points[i].x = 1;
cloud.points[i].y = 2;
cloud.points[i].z = 3;
int r = cloud.points[i].r;
int g = cloud.points[i].g;
int b = cloud.points[i].b;
cloud.points[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].normal[2] = 1024 * rand () / (RAND_MAX + 1.0f);

4、PointXYZRGBNormal

PointXYZRGBNormal存储XYZ数据和RGB颜色的point结构体,并且包括曲面法线和曲率,- float x, y, z, rgb, normal[3], curvature;

union
{
float data[4];
struct
{
float x;
float y;
float z;
};
};
union
{
float data_n[4];
float normal[3];
struct
{
float normal_x;
float normal_y;
float normal_z;
};
}
union
{
struct
{
float rgb;
float curvature;
};
float data_c[4];
};

5、PointXYZINormal

PointXYZINormal存储XYZ数据和强度值的point结构体,并且包括曲面法线和曲率, float x, y, z, intensity, normal[3], curvature;

union
{
float data[4];
struct
{
float x;
float y;
float z;
};
};
union
{
float data_n[4];
float normal[3];
struct
{
float normal_x;
float normal_y;
float normal_z;
};
}
union
{
struct
{
float intensity;
float curvature;
};
float data_c[4];
};

在这里仅列出4种类型,如果想了解更多的类型请移步:https://www.cnblogs.com/flyinggod/p/8595796.html

点云数据拼接

新建一个文件 test.cpp,然后将下面的代码复制到文件中。

#include <iostream> //标准输入输出流
#include <pcl/io/pcd_io.h> //PCL的PCD格式文件的输入输出头文件
#include <pcl/point_types.h> //PCL对各种格式的点的支持头文件
// 程序拼接A和B到C
int main (int argc, char** argv)
{
  if (argc != 2) // 需要一个参数 -f 或 -p
  {
    std::cerr << "please specify command line arg '-f' or '-p'" << std::endl;
    exit(0);
  }
    // 用于拼接不同点云的点的变量
  pcl::PointCloud<pcl::PointXYZ> cloud_a, cloud_b, cloud_c; //创建点云(不是指针),存储点坐标xyz
    // 用于拼接不同点云的域(点和法向量)的变量
  pcl::PointCloud<pcl::Normal> n_cloud_b; //创建点云,储存法向量
  pcl::PointCloud<pcl::PointNormal> p_n_cloud_c; //创建点云,储存点坐标和法向量

  //填充点云数据
  cloud_a.width  = 5; //设置宽度
  cloud_a.height = cloud_b.height = n_cloud_b.height = 1; //设置高度
  cloud_a.points.resize (cloud_a.width * cloud_a.height); //变形,无序
  if (strcmp(argv[1], "-p") == 0) //根据输入参数,设置点云
  {
    cloud_b.width  = 3; //cloud_b用于拼接不同点云的点
    cloud_b.points.resize (cloud_b.width * cloud_b.height);
  }
  else{
    n_cloud_b.width = 5; //n_cloud_b用于拼接不同点云的域
    n_cloud_b.points.resize (n_cloud_b.width * n_cloud_b.height);
  }
  for (size_t i = 0; i < cloud_a.points.size (); ++i) //设置cloud_a中点的坐标(随机数)
  {
    cloud_a.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud_a.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
    cloud_a.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
  }
  if (strcmp(argv[1], "-p") == 0)
    for (size_t i = 0; i < cloud_b.points.size (); ++i) //设置cloud_b中点的坐标(随机数)
    {
      cloud_b.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
      cloud_b.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
      cloud_b.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
    }
  else // -f
    for (size_t i = 0; i < n_cloud_b.points.size (); ++i) //设置n_cloud_b中点的坐标(随机数)
    {
      n_cloud_b.points[i].normal[0] = 1024 * rand () / (RAND_MAX + 1.0f);
      n_cloud_b.points[i].normal[1] = 1024 * rand () / (RAND_MAX + 1.0f);
      n_cloud_b.points[i].normal[2] = 1024 * rand () / (RAND_MAX + 1.0f);
    }

    // 打印拼接用的数据 A和B
  std::cerr << "Cloud A: " << std::endl;
  for (size_t i = 0; i < cloud_a.points.size (); ++i) //打印cloud_a的点坐标信息
    std::cerr << "    " << cloud_a.points[i].x << " " << cloud_a.points[i].y << " " << cloud_a.points[i].z << std::endl;

  std::cerr << "Cloud B: " << std::endl; //打印Cloud B
  if (strcmp(argv[1], "-p") == 0) //若输入参数是-p,打印cloud_b;
    for (size_t i = 0; i < cloud_b.points.size (); ++i)
      std::cerr << "    " << cloud_b.points[i].x << " " << cloud_b.points[i].y << " " << cloud_b.points[i].z << std::endl;
  else //若-f,打印n_cloud_b
    for (size_t i = 0; i < n_cloud_b.points.size (); ++i)
      std::cerr << "    " << n_cloud_b.points[i].normal[0] << " " << n_cloud_b.points[i].normal[1] << " " << n_cloud_b.points[i].normal[2] << std::endl;

  //复制点云中的点
  if (strcmp(argv[1], "-p") == 0)
  {
    cloud_c  = cloud_a;
    cloud_c += cloud_b; // cloud_a + cloud_b 意思是cloud_c包含了a和b中的点,c的点数 = a的点数+b的点数
    std::cerr << "Cloud C: " << std::endl; 打印Cloud C
    for (size_t i = 0; i < cloud_c.points.size (); ++i) //打印Cloud C
      std::cerr << "    " << cloud_c.points[i].x << " " << cloud_c.points[i].y << " " << cloud_c.points[i].z << " " << std::endl;
  }
  else //若输入参数是-f
  {
    pcl::concatenateFields (cloud_a, n_cloud_b, p_n_cloud_c); //拼接(点)cloud_a和(法向量)n_cloud_b到p_n_cloud_c
    std::cerr << "Cloud C: " << std::endl;
    for (size_t i = 0; i < p_n_cloud_c.points.size (); ++i) //打印Cloud C
      std::cerr << "    " <<
        p_n_cloud_c.points[i].x << " " << p_n_cloud_c.points[i].y << " " << p_n_cloud_c.points[i].z << " " <<
        p_n_cloud_c.points[i].normal[0] << " " << p_n_cloud_c.points[i].normal[1] << " " << p_n_cloud_c.points[i].normal[2] << std::endl;
  }

  return (0);
}

自己写了个简单的:

(注意,我一开始定义点云对象时采用

pcl::PointCloud<pcl::PointXYZ> ::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::Normal> ::Ptr cloud(new pcl::PointCloud<pcl::Normal>);
pcl::PointCloud<pcl::PointNormal> ::Ptr cloud(new pcl::PointCloud<pcl::PointNormal>);

但是这样定义以后,我发现下面这行代码会出错,至于原因我也没弄清楚,各位小伙伴有知道的还望不吝赐教在评论区???

pcl::concatenateFields(mycloud, n_cloud, np_cloud);
#include <iostream>  
#include <pcl/io/pcd_io.h>  
#include <pcl/point_types.h>   
using namespace std;
int main(int argc, char** argv)
{
	pcl::PointCloud<pcl::PointXYZ>  mycloud;//Ptr mycloud(new pcl::PointCloud<pcl::PointXYZ>)
	//pcl::PointCloud<pcl::PointXYZ> mycloud;
	mycloud.width = 100;
	mycloud.height = 1;//表示无序点云
	mycloud.is_dense = false;
	mycloud.resize(mycloud.width*mycloud.height);
	for (int i = 0; i < mycloud.points.size(); i++)
	{
		mycloud.points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
		mycloud.points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
		mycloud.points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	pcl::PointCloud<pcl::PointNormal> np_cloud;
	pcl::PointCloud<pcl::Normal> n_cloud;
	n_cloud.width = 100;
	n_cloud.height = 1;//表示无序点云
	n_cloud.is_dense = false;
	n_cloud.resize(n_cloud.width*n_cloud.height);
	for (int i = 0; i < n_cloud.points.size(); i++)
	{
		n_cloud.points[i].normal[0] = 1024 * rand() / (RAND_MAX + 1.0f);
		n_cloud.points[i].normal[1] = 1024 * rand() / (RAND_MAX + 1.0f);
		n_cloud.points[i].normal[2] = 1024 * rand() / (RAND_MAX + 1.0f);
	}
	pcl::concatenateFields(mycloud, n_cloud, np_cloud);
	//打印出写入的点
	for (size_t i = 0; i < mycloud.points.size(); ++i)
		cout << "    " << np_cloud.points[i].x<< " " << np_cloud.points[i].y<< " " << np_cloud.points[i].z 
		<< " " << np_cloud.points[i].normal[0] << " " << np_cloud.points[i].normal[1] << " " << np_cloud.points[i].normal[2] << endl;
	system("pause");
	return (0);
}

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值