PointCloud2与PointCloud类的区别
引用转载
https://www.cnblogs.com/li-yao7758258/p/6659451.html
https://blog.csdn.net/liukunrs/article/details/80319952?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~Rate-1-80319952-blog-125647921.pc_relevant_vip_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~BlogCommendFromBaidu~Rate-1-80319952-blog-125647921.pc_relevant_vip_default&utm_relevant_index=1
https://blog.csdn.net/qq_30815237/article/details/86509741
https://blog.csdn.net/weixin_42269667/article/details/117130170
内容包括
①关于pcl::PCLPointCloud2::Ptr和pcl::PointCloud<pcl::PointXYZ >两中数据结构的区别转换
②点云对象的两种定义方式的区别与转换
(1) 关于pcl::PointCloud<pcl::PointXYZ >和pcl::PCLPointCloud2::Ptr两种数据结构的区别
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<pcl::uint8_t> 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<pcl::PointXYZ>::Ptr cloud_filtered (new pcl::PointCloud<pcl::PointXYZ>), cloud_p (new pcl::PointCloud<pcl::PointXYZ>), cloud_f (new pcl::PointCloud<pcl::PointXYZ>);
// 读取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<pcl::PCLPointCloud2> 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);//我的理解是通过转化使cloud_filtered_blob<pcl::PCLPointCloud2>转变成<pcl::PointXYZ >的形式存储到cloud_filtered
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height << " data points." << std::endl;
// 保存下采样后的点云
pcl::PCDWriter writer;
writer.write<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
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<pcl::PointXYZ> ("table_scene_lms400_downsampled.pcd", *cloud_filtered, false);
**上述代码通过pcl::fromPCLPointCloud2 (cloud_filtered_blob, cloud_filtered);实现了两者的数据转化
那么依照这种的命名风格我们可以查看到更多的关于的数据格式之间的转换的类的成员
Ⅰ
void pcl::fromPCLPointCloud(const pcl:PCLPointCloud2 & msg pcl::PointCloud<PointT>
& cloud const MsgFieldMap & filed_map )
函数使用field_map实现将一个pcl::pointcloud2二进制数据blob到PCL::PointCloud对象
使用 PCLPointCloud2 (PCLPointCloud2, PointCloud)生成自己的 MsgFieldMap
*上述应该还是说的之前的转换那个意思 *后面再想想
MsgFieldMap field_map;
createMapping<PointT> (msg.fields, field_map);
Ⅱ
void pcl::fromPCLPointCloud2(const pcl::PCLPointCloud
& msg pcl::PointCloud<pointT> &cloud)
把pcl::PCLPointCloud数据格式的点云转化为pcl::PointCloud< pointT >格式
定义点云的数据格式及调试代码遇到的问题
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT;
PointCloudT::Ptr cloud_;
对比下 点云的定义
typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT
PointCloudT::Ptr cloud (new PointCloudT);
PointCloudT::Ptr cloud_filtered (new PointCloudT)
对比我们可以看出,这里两种定义的方法的不同。
PointCloudT::Ptr cloud_;
PointCloudY::Ptr cloud_tmp(new PointCloudT)
在构造上的区别:常规变量定义不使用new,定义的对象在定义后就自动可以使用,指针变量定义必须使用new进行对象实例的构造。
使用上的区别:使用new的是一个指针对象,此时对对象成员的访问需要使用指针操作符“->”,而不使用new的是常规对象,使用普通成员操作符“.”。
两者如何去转换
pcl::copyPointCloud (*cloud_tmp, *cloud_);
②点云对象的两种定义方式的区别与转换
第一种,是一种vector的赋值方式,将point数据push_back到pcl::PointXYZ类型的模板中。
pcl::PointCloud<pcl::PointXYZ> pointCloud;
pcl::PointXYZ point;
point.x = 2.0f - y;
point.y = y;
point.z = z;
pointCloud.points.push_back(point);
第二种,指针型类模板,采用“->points[i]”方式赋值。
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
for (int i = 0; i < cloud->points.size (); ++i)
{
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);
}
pcl::PointCloud::Ptr和pcl::PointCloud可以相互转换
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPtr(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PointCloud<pcl::PointXYZ> cloud;
cloud = *cloudPtr;//由Ptr转变为另一种类型
cloudPtr = cloud.makeShared();//转变为Ptr类型
cloud.makeShared()解释
pcl::PointCloud.makeshared()返回的是一个对当前点云深度复制后的对象的智能指针,
也就是说
pcl::PointCloud cloud;
pcl::PointCloud::Ptr p= cloud.makeshared();
p并不指向cloud的空间,而是先深度拷贝了cloud放在新空间,然后返回指向该空间的指针。
通过p来操作点云,cloud不会改变。
所以用pcl定义点云的时候多用pcl::PointCloud::Ptr p(new pcl::PointCloud)吧,传指针减少开销,还不会因为在传指针的时候因为makeshared被坑。
pcl::PointCloud::Ptr和pcl::PointCloud两种对象,在操作shang是会有所不同
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile("E:\\test_PCL\\pipline.pcd",*cloud) == -1)
pcl::PointCloud<pcl::PointXYZ> cloud;
pcl::io::loadPCDFile("E:\\test_PCL\\pipline.pcd",cloud) == -1)
且kdtree和octree类中的setInputCloud()函数只支持Ptr类型,如果点云对象不是Ptr类型,需要进行类型转换。
以下为实例
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
using namespace std;
void VisualizeCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud, pcl::PointCloud<pcl::PointXYZ>::Ptr& filter_cloud) { //定义一个可视化的函数 注意传参数的类型
//-----------------------显示点云-----------------------
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("显示点云"));
int v1(0), v2(0), v3(0);
viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
viewer->setBackgroundColor(0, 0, 0, v1);
viewer->addText("point clouds", 10, 10, "v1_text", v1);
viewer->createViewPort(0.5, 0.0, 1, 1.0, v2);
viewer->setBackgroundColor(0.1, 0.1, 0.1, v2);
viewer->addText("filtered point clouds", 10, 10, "v2_text", v2);
// 按照z字段进行渲染,将z改为x或y即为按照x或y字段渲染
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "z");
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "sample cloud", v1);
viewer->addPointCloud<pcl::PointXYZ>(filter_cloud, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 0, 1, 0, "cloud_filtered", v2);
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_COLOR, 1, 0, 0, "cloud_out", v3);
//viewer->addCoordinateSystem(1.0);
//viewer->initCameraParameters();
while (!viewer->wasStopped())
{
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int main() {
pcl::PCLPointCloud2::Ptr cloud(new pcl::PCLPointCloud2());
pcl::PointCloud<pcl::PointXYZ>::Ptr p(new pcl::PointCloud<pcl::PointXYZ>); //多定义两个p/q便于类型转换
pcl::PointCloud<pcl::PointXYZ>::Ptr q(new pcl::PointCloud<pcl::PointXYZ>);
/*pcl::PointCloud<pcl::PCLPointCloud2>::Ptr cloud(new pcl::PointCloud<pcl::PCLPointCloud2>);*/
pcl::PCDReader reader;
reader.read("C:\\Users\\Administrator\\Desktop\\plot1.pcd", *cloud);
//pcl::io::loadPCDFile<pcl::PointXYZ>("C:\\Users\\Administrator\\Desktop\\data\\shumu.pcd", *cloud);//读取pcd
pcl::PCLPointCloud2::Ptr cloud_filtered(new pcl::PCLPointCloud2()); //现创建后续备用
//先进行降采样,减少计算压力;
std::cerr << "PointCloud before filtering: " << cloud->width * cloud->height
<< " data points (" << pcl::getFieldsList(*cloud) << ")." << std::endl;//计算点云数量
// Create the filtering object
//设置体素滤波器
pcl::VoxelGrid<pcl::PCLPointCloud2> sor;
sor.setInputCloud(cloud); //输入点云
sor.setLeafSize(0.5f, 0.5f, 0.5f); //体素滤波器,单位m
sor.filter(*cloud_filtered); //滤波后的点云
std::cerr << "PointCloud after filtering: " << cloud_filtered->width * cloud_filtered->height
<< " data points (" << pcl::getFieldsList(*cloud_filtered) << ")." << std::endl;
pcl::PCDWriter writer;
writer.write("C:\\Users\\Administrator\\Desktop\\plot5.pcd", *cloud_filtered);
pcl::fromPCLPointCloud2(*cloud , *p); //转换类型,将pcl::PCLPointCloud2转变成pcl::PointXYZ,以便适应传参数的需要
pcl::fromPCLPointCloud2(*cloud_filtered, *q);
VisualizeCloud(p, q);
}