博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PCL中点云数据格式之间的转化
阅读量:4569 次
发布时间:2019-06-08

本文共 6262 字,大约阅读时间需要 20 分钟。

(1) 关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ>两中数据结构的区别

pcl::PointXYZ::PointXYZ ( float_x,                  float_y,                  float_z                    )

区别:    

struct PCLPointCloud2 {  PCLPointCloud2 () : header (), height (0), width (0), fields (), is_bigendian (false), point_step (0), row_step (0),  data (), is_dense (false)  { #if defined(BOOST_BIG_ENDIAN)  is_bigendian = true; #elif defined(BOOST_LITTLE_ENDIAN)  is_bigendian = false; #else #error "unable to determine system endianness" #endif  }   ::pcl::PCLHeader header;   pcl::uint32_t height;  pcl::uint32_t width;   std::vector< ::pcl::PCLPointField> fields;   pcl::uint8_t is_bigendian;  pcl::uint32_t point_step;  pcl::uint32_t row_step;   std::vector
data; pcl::uint8_t is_dense; public: typedef boost::shared_ptr< ::pcl::PCLPointCloud2> Ptr; typedef boost::shared_ptr< ::pcl::PCLPointCloud2 const> ConstPtr; }; // struct PCLPointCloud2

那么要实现它们之间的数据转换,

举个例子

pcl::PCLPointCloud2::Ptr cloud_blob (new pcl::PCLPointCloud2), cloud_filtered_blob (new pcl::PCLPointCloud2);//申明滤波前后的点云  pcl::PointCloud
::Ptr cloud_filtered (new pcl::PointCloud
), cloud_p (new pcl::PointCloud
), cloud_f (new pcl::PointCloud
); // 读取PCD文件 pcl::PCDReader reader; reader.read ("table_scene_lms400.pcd", *cloud_blob); //统计滤波前的点云个数 std::cerr << "PointCloud before filtering: " << cloud_blob->width * cloud_blob->height << " data points." << std::endl; // 创建体素栅格下采样: 下采样的大小为1cm pcl::VoxelGrid
sor; //体素栅格下采样对象 sor.setInputCloud (cloud_blob); //原始点云 sor.setLeafSize (0.01f, 0.01f, 0.01f); // 设置采样体素大小 sor.filter (*cloud_filtered_blob); //保存 // 转换为模板点云 pcl::fromPCLPointCloud2 (*cloud_filtered_blob, *cloud_filtered); std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl; // 保存下采样后的点云 pcl::PCDWriter writer; writer.write
("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);

程序中红色部分就是一句实现两者之间的数据转化的我们可以看出

cloud_filtered_blob 声明的数据格式为pcl::PCLPointCloud2::Ptr  cloud_filtered_blob (new pcl::PCLPointCloud2);
cloud_filtered 申明的数据格式  pcl::PointCloud
::Ptr cloud_filtered (new pcl::PointCloud
)

那么依照这种的命名风格我们可以查看到更多的关于的数据格式之间的转换的类的成员

(1)

   void pcl::fromPCLPointCloud(const pcl:PCLPointCloud2 & msg

                                                   pcl::PointCloud<PointT>  & cloud

                                                     const MsgFieldMap & filed_map

                                                     )

函数使用field_map实现将一个pcl::pointcloud2二进制数据blob到PCL::PointCloud<pointT>对象

使用 PCLPointCloud2 (PCLPointCloud2, PointCloud<T>)生成自己的 MsgFieldMap

MsgFieldMap field_map;createMapping
(msg.fields, field_map);

(2)

void pcl::fromPCLPointCloud2(const pcl::PCLPointCloud & msg

                                                  pcl::PointCloud<pointT> &cloud

                                                  )

把pcl::PCLPointCloud数据格式的点云转化为pcl::PointCloud<pointT>格式

(3)

 void pcl::fromROSMsg(const pcl:PCLPointCloud2 & msg

                                 pcl::PointCloud<PointT>  & cloud

                                  const MsgFieldMap & filed_map

                                     )

(4)

 void pcl::fromROSMsg(const pcl:PCLPointCloud2 & msg

                                  pcl::PointCloud<PointT>  & cloud

                                     )

在使用fromROSMsg是一种在ROS 下的一种数据转化的作用,我们举个例子实现订阅使用kinect发布   /camera/depth/points  从程序中我们可以看到如何使用该函数实现数据的转换。并且我在程序中添加了如果使用PCL的库实现在ROS下调用并且可视化,

/************************************************关于如何使用PCL在ROS 中,实现简单的数据转化时间:2017.3.31****************************************************/#include 
// PCL specific includes#include
#include
#include
#include
#include
#include
#include
ros::Publisher pub; pcl::visualization::CloudViewer viewer("Cloud Viewer");void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input){ // 创建一个输出的数据格式 sensor_msgs::PointCloud2 output; //ROS中点云的数据格式 //对数据进行处理pcl::PointCloud
::Ptr cloud (new pcl::PointCloud
); output = *input; pcl::fromROSMsg(output,*cloud); //blocks until the cloud is actually rendered viewer.showCloud(cloud); pub.publish (output);}intmain (int argc, char** argv){ // Initialize ROS ros::init (argc, argv, "my_pcl_tutorial"); ros::NodeHandle nh; // Create a ROS subscriber for the input point cloud ros::Subscriber sub = nh.subscribe ("input", 1, cloud_cb); ros::Rate loop_rate(100); // Create a ROS publisher for the output point cloud pub = nh.advertise
("output", 1); // Spin ros::spin ();/*while (!viewer.wasStopped ()) { } */ }

那么对于这一段小程序实现了从发布的节点中转化为可以使用PCL的可视化函数实现可视化,并不一定要用RVIZ来实现,所以我们分析以下其中的步骤,在订阅话题的回调函数中,

void  cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input)        //这里面设置了一个数据类型为sensor_msgs::PointCloud2ConstPtr& input形参

{
  sensor_msgs::PointCloud2 output;                                //ROS中点云的数据格式(或者说是发布话题点云的数据类型)
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>);     //对数据转换后存储的类型
  output = *input;
   pcl::fromROSMsg(output,*cloud);   //最重要的一步骤实现从ROS到PCL中的数据的转化,同时也可以直接使用PCL库实现可视化

  viewer.showCloud(cloud);  //PCL库的可视化

  pub.publish (output);     //那么原来的output的类型仍然是sensor_msgs::PointCloud2,可以通过RVIZ来可视化
}

那么也可以使用

pcl::PCDWriter writer;  writer.write
("ros_to_PCL.pcd", *cloud, false);

这一段代码来实现保存的作用。那么见到那看一下可视化的结果

使用pcl_viewer 可视化保存的PCD文件

于2018年5月5号看到再次更新一点小笔记,比如我们在写程序的过程中经常会遇到定义点云的数据格式为

typedef pcl::PointXYZRGB PointT;typedef pcl::PointCloud
PointCloudT;PointCloudT::Ptr cloud_;

但是我们在运行一个简单的例程比如直通滤波器的内容是一般的点云的定义为

typedef pcl::PointXYZRGB PointT;typedef pcl::PointCloud
PointCloudTPointCloudT::Ptr cloud (new PointCloudT);PointCloudT::Ptr cloud_filtered (new PointCloudT) pcl::PassThrough
pass; pass.setInputCloud (cloud); //设置输入点云 pass.setFilterFieldName ("z"); //设置过滤时所需要点云类型的Z字段 pass.setFilterLimits (0.0, 1.0); //设置在过滤字段的范围 //pass.setFilterLimitsNegative (true); //设置保留范围内还是过滤掉范围内 pass.filter (*cloud_filtered); //执行滤波,保存过滤结果在cloud_filtered

对比我们可以看出

这里两种定义的方法的不同是不能在直通滤波器直接使用的

PointCloudT::Ptr   cloud_;PointCloudY::Ptr   cloud_tmp(new PointCloudT)

如何去转换呢?

如下:

pcl::copyPointCloud (*cloud_tmp, *cloud_);

在构造上的区别:常规变量定义不使用new,定义的对象在定义后就自动可以使用,指针变量定义必须使用new进行对象实例的构造。

使用上的区别:使用new的是一个指针对象,此时对对象成员的访问需要使用指针操作符“->”,而不使用new的是常规对象,使用普通成员操作符“.”。

 

可能写的比较乱,但是有用到关于PCL中点云数据类型的转换以及可视化等功能可以参考,同时欢迎有兴趣者扫描下方二维码或者QQ群

与我交流并且投稿,大家一起学习,共同进步与分享

  

转载于:https://www.cnblogs.com/li-yao7758258/p/6659451.html

你可能感兴趣的文章
[转]基本Guava工具
查看>>
趁着没断网,赶快写总结
查看>>
Eclipse中取消按空格选中自动提示
查看>>
JAVA的Date类与Calendar类比较
查看>>
iOS开发拓展篇—音乐的播放
查看>>
Flink资料(1)-- Flink基础概念(Basic Concept)
查看>>
[BZOJ4012] [HNOI2015]开店
查看>>
iOS5新开发的API总述——WWDC 2011
查看>>
JavaScript 基础——使用js的三种方式,js中的变量,js中的输出语句,js中的运算符;js中的分支结构...
查看>>
基于IdentityServer4的OIDC实现单点登录(SSO)原理简析
查看>>
Multicast Routing
查看>>
java NIO中的buffer和channel
查看>>
使用JRegistry来操作window系统注册表
查看>>
函数递归,算法之二分法,表达式,生成式,匿名函数及常用内置函数
查看>>
Nginx,uWSGI与Django 应用的关系
查看>>
Html显示地图
查看>>
MySQL索引选择问题(要相信MySQL自己选择索引的能力)
查看>>
Angular i18n
查看>>
1104文法分析
查看>>
常见adb命令
查看>>