《点云库PCL学习教程》第6章 八叉树_第1页
《点云库PCL学习教程》第6章 八叉树_第2页
《点云库PCL学习教程》第6章 八叉树_第3页
《点云库PCL学习教程》第6章 八叉树_第4页
《点云库PCL学习教程》第6章 八叉树_第5页
已阅读5页,还剩59页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章八叉树建立空间索引在点云数据处理中已被广泛应用,常见空间索引一般是自顶向下逐级划分空间的各种空间索引结构,比较有代表性的包括BSP树、KD树、KDB树、R树、R+树、CELL树、四叉树和八叉树等索引结构,而在这些结构中KD树和八叉树在3D点云数据组织中应用较为广泛。PCL对八叉树的数据结构建立和索引方法进行了实现,以方便在此基础上的其他点云处理操作。本章首先对常用的点云空间索引方法octree概念进行介绍,然后对PCL的octree相关模块及类进行简单说明,最后通过应用实例来展示如何对PCL中octree模块进行灵活运用。本章各小节目录6.1octree概述及相关算法简介6.2PCL中octree模块及类介绍6.3应用实例解析6.1octree概述及相关算法简介八叉树结构是由Hunter博士于1978年首次提出的一种数据模型。八叉树结构通过对三维空间的几何实体进行体元剖分,每个体元具有相同的时间和空间复杂度,通过循环递归的划分方法对大小为2n×2n×2n的三维空间的几何对象进行剖分,从而构成一个具有根节点的方向图。在八叉树结构中如果被划分的体元具有相同的属性,则该体元构成一个叶节点;否则继续对该体元剖分成8个子立方体,依次递归剖分,对于2n×2n×2n大小的空间对象,最多剖分n次,如图6-1所示。

6.2PCL中octree模块及类介绍PCL中octree库提供了octree数据结构,利用FLANN进行快速邻域检索。邻域检索在匹配、特征描述子计算、领域特征提取中是非常基础的核心操作。octree模块利用十几个类实现了利用octree数据结构对点云的高效管理和检索,以及相应的一些空间处理算法,例如压缩、空间变化检测,其依赖于pcl_common模块。octree模块中类说明目前PCL中octree模块中目前共有16个类,以后有可能增加。1.classpcl::octree::Octree2BufBase<DataT,LeafT>类Octree2BufBase实现了同时存储管理两个八叉树于内存中,如此,可以非常高效地实现八叉树的建立管理等操作,并且该类实现对临近树节点结构的变化探测,对应到空间点云,其就可以对空间曲面的动态变化进行探测,在进行空间动态变化探测中非常有用,例如目前基于kinect设备的体感交互应用。类Octree2BufBase关键成员函数:voidsetMaxVoxelIndex(unsignedintmaxVoxelIndex_arg)设置在各个维度上最大的体素个数。voidsetTreeDepth(unsignedintdepth_arg)设置八叉树的深度,需要在初始化八叉树时设置。voidadd(unsignedintidxX_arg,unsignedidxY_arg,unsignedintidxZ_arg,constDataT&data_arg)在idxX、idxY、idxZ对应的叶子节点上填充DataT的数据,其中idxX、idxY、idxZ为在三个维度上的整型索引值。boolexistLeaf(unsignedintidxX_arg,unsignedintidxY_arg,unsignedintidxZ_arg)const判断在idxX、idxY、idxZ对应的叶子节点是否存在,如果存在返回true,否则返回false。unsignedintgetLeafCount()const返回在该八叉树中的叶子数目。unsignedintgetBranchCount()const返回在该八叉树中的分支数目。voiddeleteTree(boolfreeMemory_arg=false)删除八叉树的结构及其叶子节点。voiddeletePreviousBuffer()删除另一个缓冲区中对应八叉树的结构及其叶子节点。voiddeleteCurrentBuffer()删除当前缓冲区中对应八叉树的结构和其叶子节点。voidswitchBuffers()交换缓冲区,并重设八叉树结构。voidserializeTree(std::vector<char>&binaryTreeOut_arg,booldoXOREncoding_arg=false)串行化输出八叉树结构到binaryTreeOut_arg向量,doXOREncoding_arg设置输出时是否将当前缓冲区与后台缓冲区中数据进行异或操作后再输出,异或操作是两个八叉树结构之间差异数据的输出。voidserializeTree(std::vector<char>&binaryTreeOut_arg,std::vector<DataT>&dataVector_arg,booldoXOREncoding_arg=false)串行化重载函数,其中参数dataVector_arg存储八叉树中叶子节点上的数据,其他两个参数同上。voidserializeLeafs(std::vector<DataT>&dataVector_arg)参数dataVector_arg存储八叉树中叶子节点上的数据,该函数只串行化八叉树中的数据。voidserializeNewLeafs(std::vector<DataT>&dataVector_arg,constintminPointsPerLeaf_arg=0)串行化当前缓冲区八叉树中存在但在后台缓冲区八叉树中不存在的节点数据,其中,minPointsPerLeaf_arg为需要串行化的节点中点的最小个数,如果点个数小于该值则不串行化此新节点。voiddeserializeTree(std::vector<char>&binaryTreeIn_arg,booldoXORDecoding_arg=false)反串行化,参数意义上同上面对应的串行化函数。2.classpcl::octree::OctreeBase<DataT,LeafT,OctreeBranchT>类OctreeBase为八叉树基类,其关键成员函数参考其他类介绍。3.classpcl::octree::OctreeBaseWithState<DataT,LeafT>类OctreeBaseWithState为带有状态的八叉树基类,其中额外存储的状态多用于可见性估计,同样其关键成员函数参考其他类的介绍。4.classpcl::octree::OctreeIteratorBase<DataT,LeafT,OctreeT>类OctreeIteratorBase为八叉树迭代器的基类,用于深度优先或广度优先遍历八叉树时使用。类OctreeIteratorBase关键成员函数:voidreset()初始化迭代器。constOctreeKey&getCurrentOctreeKey()const获取当前八叉树节点对应迭代器的键值。unsignedintgetCurrentOctreeDepth()const获取当前八叉树迭代器对应节点所在的深度值。constOctreeNode*getCurrentOctreeNode()const获取当前八叉树节点。boolisBranchNode()const判断当前节点是否为分支节点,是返回true,否则返回false。boolisLeafNode()const判断当前节点是否为叶子节点,是返回true,否则返回false。chargetNodeConfiguration()const获取当前节点的设置对应的比特位值。virtualvoidgetData(constDataT*&data_arg)const获取当前节点包含数据的首个元素。virtualvoidgetData(std::vector<DataT>&dataVector_arg)const获取当前节点对应的向量数据。virtualunsignedlonggetNodeID()const获取当前节点对应的整数ID。5.Classpcl::octree::OctreeDepthFirstIterator<DataT,LeafT,OctreeT>6.classpcl::octree::OctreeDepthFirstIterator<DataT,LeafT,OctreeT>7.classpcl::octree::OctreeLeafNodeIterator<DataT,LeafT,OctreeT>以上3个类都继承于OctreeIteratorBase,分别实现深度优先遍历、广度优先遍历、叶子节点迭代器,关键函数参考其基类。8.classpcl::octree::OctreePointCloud<PointT,LeafT,OctreeT>类OctreePointCloud为针对点云实现的八叉树数据结构与相关算法,基于该类继承出多个子类,实现不同的点云处理或操作,如图6-2所示。类OctreePointCloud关键成员函数:voidsetInputCloud(constPointCloudConstPtr&cloud_arg,constIndicesConstPtr&indices_arg=IndicesConstPtr())设置八叉树管理的点云,其中cloud_arg为指向点云对象的指针,indices_arg为真正需要输入的点云的索引序列。voidsetEpsilon(doubleeps)设置近邻搜索时的误差限。voidsetResolution(doubleresolution_arg)设置为点云建立的八叉树结构的分辨率,即体素的大小。voidaddPointsFromInputCloud()显示调用将点云添加到八叉树管理结构中。voidaddPointFromCloud(constintpointIdx_arg,IndicesPtrindices_arg)添加对应索引中的点到八叉树中,其中pointIdx_arg为索引,indices_arg索引序列的指针。voidaddPointToCloud(constPointT&point_arg,PointCloudPtrcloud_arg,IndicesPtrindices_arg)添加点point_arg到点云cloud_arg的indices_arg索引下,同时添加到八叉树中。boolisVoxelOccupiedAtPoint(constPointT&point_arg)const判断点point_arg所处的空间是否存在八叉树体素中。boolisVoxelOccupiedAtPoint(constdoublepointX_arg,constdoublepointY_arg,constdoublepointZ_arg)const判断点(pointX_arg,pointY_arg,pointZ_arg)所处的空间是否存在八叉树体素中。intgetOccupiedVoxelCenters(AlignedPointTVector&voxelCenterList_arg)const获取所有被点云占据的体素的中心并存储在voxelCenterList_arg中,返回值为被占据的体素的个数。intgetApproxIntersectedVoxelCentersBySegment(constEigen::Vector3f&origin,constEigen::Vector3f&end,AlignedPointTVector&voxel_center_list,floatprecision=0.2)用参数origin和end给定空间一线段,该函数求得与该线段相交的体素中心,存储在voxel_center_list,并返回相交体素的个数。voiddeleteVoxelAtPoint(constPointT&point_arg)删除指定点所在的八叉树所管理的体素或叶子节点。voiddefineBoundingBox(constdoubleminX_arg,constdoubleminY_arg,constdoubleminZ_arg,constdoublemaxX_arg,constdoublemaxY_arg,constdoublemaxZ_arg)指定八叉树的包围盒,参数为三个维度的上下限,八叉树中一旦存储管理元素了,则包围盒大小就不能再改变。voidgetBoudingBox(double&minX_arg,double&minY_arg,double&minZ_arg,double&maxX_arg,double&maxY_arg,double&maxZ_arg)const获取包围盒3个维度的上下限。doublegetVoxelSquaredDiameter(unsignedinttreeDepth_arg)const获取八叉树中指定深度对应体素的内切圆的直径。doublegetVoxelSquaredSideLen(unsignedinttreeDepth_arg)const获取八叉树中指定深度对应体素的立方体的边长。9.classpcl::octree::OctreePointCloudChangeDetector<PointT,LeafT>类OctreePointCloudChangeDetector实现了创建一八叉树,该八叉树由新增加的叶子节点组成,该八叉树分辨率需要初始化,包围盒可自适应调整。类OctreePointCloudChangeDetector关键成员函数,未列出的参考其父类OctreePointCloud:intgetPointIndicesFromNewVoxels(std::vector<int>&indicesVector_arg,constintminPointsPerLeaf_arg=0)获取缓存区中新添加的叶子节点,indicesVector_arg为新添加的叶子的索引向量,intminPointsPerLeaf_arg设置需要串行化的叶子中应该包含点的最小数目。voidsetEpsilon(doubleeps)设置近邻搜索时的误差限。voidsetInputCloud(constPointCloudConstPtr&cloud_arg,constIndicesConstPtr&indices_arg=IndicesConstPtr())设置输入点云,其中cloud_arg表示输入的点云对象指针,indices_arg表示真正作为输入的点集的索引向量。voidsetResolution(doubleresolution_arg)设置八叉树分辨率。voidaddPointsFromInputCloud()添加利用setInputCloud函数设置的点云到八叉树中。10.classpcl::octree::OctreePointCloudDensity<PointT,LeafT,OctreeT>类OctreePointCloudDensity实现了管理一八叉树,其叶子节点并非存储点云,只是对处于其叶子体素中的点云个数进行存储,即整个八叉树的叶子节点存储了输入点云的密度空间分布。类OctreePointCloudDensity关键成员函数,未列出的参考其父类OctreePointCloud:unsignedintgetVoxelDensityAtPoint(constPointT&point_arg)const返回point_arg点所在的叶子节点体素的密度,即该点所在的体素中包含点的个数。11.classpcl::octree::OctreePointCloudOccupancy<PointT,LeafT,OctreeT>类OctreePointCloudOccupancy实现了管理一八叉树,其叶子节点不存储任何数据,只是对输入点云所占据的空间通过叶子所处的体素来进行标志,这样就可以对点云所占据空间的情况进行评估和检测。类OctreePointCloudOccupancy关键成员函数,未列出的参考其父类OctreePointCloud:voidsetOccupiedVoxelAtPoint(constPointT&point_arg)在点point_arg所在空间为八叉树添加叶子节点,标识其有点云占据该节点所在体素空间。voidsetOccupiedVoxelsAtPointsFromCloud(PointCloudPtrcloud_arg)在点集cloud_arg所在空间为八叉树添加叶子节点,标识其有点云占据该节点所在体素空间。12.classpcl::octree::OctreePointCloudPointVector<PointT,LeafT,OctreeT>类OctreePointCloudPointVector管理一八叉树,该八叉树叶子节点,存储处在该节点体素中的点对应的索引向量。类OctreePointCloudOccupancy关键成员函数,未列出的参考其父类OctreePointCloud:voidsetEpsilon(doubleeps)设置近邻搜索时的误差限。voidsetInputCloud(constPointCloudConstPtr&cloud_arg,constIndicesConstPtr&indices_arg=IndicesConstPtr())设置输入点云,其中cloud_arg表示输入的点云对象指针,indices_arg表示真正作为输入的点集的索引向量。voidsetResolution(doubleresolution_arg)设置八叉树分辨率。13.classpcl::octree::OctreePointCloudSinglePoint<PointT,LeafT,OctreeT>类OctreePointCloudSinglePoint管理一八叉树,该八叉树叶子节点,存储处在该节点体素中的单个点的索引,其关键函数参考类OctreePointCloudPointVector。14.classpcl::octree::OctreePointCloudVoxelCentroid<PointT,LeafT,OctreeT>类OctreePointCloudVoxelCentroid管理一八叉树,可提供被点云占据节点对应体素的中心点坐标。类OctreePointCloudVoxelCentroid关键成员函数,未列出的参考其父类OctreePointCloud:unsignedintgetVoxelCentroids(AlignedPointTVector&voxelCentroidList_arg)返回所有被点云占据的叶子节点的中心点组成的向量,存储在voxelCentroidList_arg中,返回值为返回中心的个数。boolgetVoxelCentroidAtPoint(constPointT&point_arg,PointT&voxelCentroid_arg)返回点point_arg对应的节点体素的中心点,存储在voxelCentroid_arg中,返回值为true表示操作成功,否则表示操作失败。boolgetVoxelCentroidAtPoint(constint&pointIdx_arg,PointT&voxelCentroid_arg)返回索引pointIdx_arg对应点所代表的节点体素中心点,存储在voxelCentroid_arg中,返回值为true表示成功,否则表示操作失败。15.Classpcl::octree::OctreePointCloudSearch<PointT,LeafT,OctreeT>类OctreePointCloudSearch实现了基于八叉树的点云近邻高效搜索。类OctreePointCloudSearch关键成员函数:boolvoxelSearch(constPointT&point,std::vector<int>&pointIdx_data)给定查询点point,通过point确定其所在的体素,返回体素中所有点的索引存储在pointIdx_data。boolvoxelSearch(constintindex,std::vector<int>&pointIdx_data)功能同上函数,区别是查询点通过index指定。intnearestKSearch(constPointCloud&cloud,intindex,intk,std::vector<int>&k_indices,std::vector<float>&k_sqr_distances)近邻搜索,cloud为搜索的点云对象,index为查询点的索引,k为搜索返回的近邻个数,k_indices为返回近邻索引向量,k_sqr_distances存储近邻点对应的距离平方向量。intnearestKSearch(constPointT&p_q,intk,std::vector<int>&k_indices,std::vector<float>&k_sqr_distances)功能同上,p_q为指定的查询点,其他参数类似。voidapproxNearestSearch(constPointCloud&cloud,intquery_index,int&result_index,float&sqr_distance)近似近邻搜索,其他参数同上。intradiusSearch(constPointCloud&cloud,intindex,doubleradius,std::vector<int>&k_indices,std::vector<float>&k_sqr_distances,unsignedintmax_nn=0)获取查询点radius半径内的近邻点集,cloud为搜索的点云对象,index为查询点的索引,k为搜索返回的近邻个数,k_indices为返回近邻索引向量,k_sqr_distances存储近邻点对应的距离平方向量,max_nn默认为0,如果设置就返回半径内邻域个数上限,返回值为返回领域点的个数。intgetIntersectedVoxelCenters(Eigen::Vector3forigin,Eigen::Vector3fdirection,AlignedPointTVector&voxelCenterList)const给定经过点origin指向direction的直线,返回与该直线相交的点云对应八叉树的体素中心点组成的向量,并存储在voxelCenterList中,返回值为相交体素个数。intgetIntersectedVoxelIndices(Eigen::Vector3forigin,Eigen::Vector3fdirection,std::vector<int>&k_indices)const功能同上函数,k_indices存储相交体素的索引。intboxSearch(constEigen::Vector3f&min_pt,constEigen::Vector3f&max_pt,std::vector<int>&k_indices)const搜索处于指定立方体内的点集,min_pt、max_pt指定立方体的左前下角坐标及右后上方坐标来定义立方体,k_indices存储落在立方体内的点的索引。voidsetInputCloud(constPointCloudConstPtr&cloud_arg,constIndicesConstPtr&indices_arg=IndicesConstPtr())指定构建八叉树的点云。voidsetEpsilon(doubleeps)设置搜索时的精度。voidsetResolution(doubleresolution_arg)设置八叉树的体素分辨率。voidaddPointsFromInputCloud()显示调用将点云添加到八叉树管理结构中。voidaddPointFromCloud(constintpointIdx_arg,IndicesPtrindices_arg)添加对应索引中的点到八叉树中,其中pointIdx_arg为索引,indices_arg索引序列的指针。voidaddPointToCloud(constPointT&point_arg,PointCloudPtrcloud_arg,IndicesPtrindices_arg)添加点point_arg到点云cloud_arg的indices_arg索引下,同时添加到八叉树中。boolisVoxelOccupiedAtPoint(constPointT&point_arg)const判断点point_arg所处的空间是否存在于八叉树体素中。boolisVoxelOccupiedAtPoint(constdoublepointX_arg,constdoublepointY_arg,constdoublepointZ_arg)const判断点(pointX_arg,pointY_arg,pointZ_arg)所处的空间是否存在于八叉树体素中。intgetOccupiedVoxelCenters(AlignedPointTVector&voxelCenterList_arg)const返回所有被点云占据的体素的中心存储在voxelCenterList_arg中,返回值为被占据的体素的个数。intgetApproxIntersectedVoxelCentersBySegment(constEigen::Vector3f&origin,constEigen::Vector3f&end,AlignedPointTVector&voxel_center_list,floatprecision=.2)用参数origin和end给定空间一线段,该函数求得与该线段相交的体素中心,存储在voxel_center_list,并返回相交体素的个数。voiddeleteVoxelAtPoint(constPointT&point_arg)删除指定点所在的八叉树中管理的体素或叶子节点。voiddefineBoundingBox(constdoubleminX_arg,constdoubleminY_arg,constdoubleminZ_arg,constdoublemaxX_arg,constdoublemaxY_arg,constdoublemaxZ_arg)指定八叉树的包围盒,参数为3个维度的上下限,八叉树中一旦存储管理元素了,则包围盒大小就不能再改变。voidgetBoudingBox(double&minX_arg,double&minY_arg,double&minZ_arg,double&maxX_arg,double&maxY_arg,double&maxZ_arg)const获取包围盒子3个维度的上下限。doublegetVoxelSquaredDiameter(unsignedinttreeDepth_arg)const获取八叉树中指定深度对应体素的内切圆的直径。doublegetVoxelSquaredSideLen(unsignedinttreeDepth_arg)const获取八叉树中指定深度对应体素的立方体的边长。6.3应用实例解析6.3.1在PCL中如何实现点云压缩点云由海量的数据集组成,这些数据集通过距离、颜色、法线等附加信息来描述空间三维点。此外,点云能以非常高的速率被创建出来,因此需要占用相当大的存储资源,一旦点云需要存储或者通过速率受限制的通信信道进行传输,提供针对这种数据的压缩方法就变得十分有用。PCL库提供了点云压缩功能,它允许编码压缩所有类型的点云,如图6-3所示,包括“无序”点云,它具有无参考点和变化的点尺寸、分辨率、分布密度和点顺序等结构特征。而且,底层的octree数据结构允许从几个输入源高效地合并点云数据。下面解释单个点云和点云数据流是如何高效压缩的,在给出的例子中用PCL点云压缩技术来压缩用OpenNIGrabber抓取到的点云。在本书提供光盘的第6章例1文件夹中打开名为point_cloud_compression.cpp的代码文件。1.代码解释说明下面详细解析打开的源代码。从主函数开始首先创建一个新的SimpleOpenNIViewer实例并调用它的run()方法。intmain(intargc,char**argv){SimpleOpenNIViewerv;v.run();return(0);}在run()函数中创建PointCloudCompression类的对象来编码和解码,这些对象把压缩配置文件作为配置压缩算法的参数,所提供的压缩配置文件为OpenNI兼容设备采集到的点云预先确定的通用参数集。本例中使用MED_RES_ONLINE_COMPRESSION_WITH_COLOR配置参数集,它应用5mm的编码精度并且允许彩色纹理成分编码,并进一步优化,用于快速在线压缩。压缩配置文件的完整列表及其配制方法可以在文件“/io/include/pcl/compression/compression_profiles.h”中找到。在PointCloudCompression构造函数中使用MANUAL_CONFIGURATION属性就可以手动设置压缩算法全部参数。boolshowStatistics=true;//设置在标准设备上输出打印出压缩结果信息//压缩选项详见/io/include/pcl/compression/compression_profiles.h3pcl::octree::compression_Profiles_ecompressionProfile=pcl::octree::MED_RES_ONLINE_COMPRESSION_WITH_COLOR;//初始化压缩与解压缩对象,其中压缩对象需要设定压缩参数选项,解压缩按照数据源自行判断pointCloudEncoder=newpcl::octree::PointCloudCompression<pcl::PointXYZRGBA>(compressionProfile,showStatistics);pointCloudDecoder=newpcl::octree::PointCloudCompression<pcl::PointXYZRGBA>();下面的代码为OpenNI兼容设备实例化一个新的采集器,并且启动循环回调接口,每从设备获取一帧数据就调用回调函数一次,这里的回调函数实现数据压缩和可视化解压缩结果。//创建从OpenNI获取点云的抓取对象pcl::Grabber*interface=newpcl::OpenNIGrabber();boost::function<void(constpcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&)>f=boost::bind(&SimpleOpenNIViewer::cloud_cb_,this,_1);//建立回调函数//建立回调函数与回调信号之间绑定boost::signals2::connectionc=interface->registerCallback(f);//开始接收点云数据流interface->start();while(!viewer.wasStopped()){sleep(1);}interface->stop();在OpenNIGrabber采集循环执行的回调函数cloud_cb_中,首先把获取到的点云压缩到stringstream缓冲区,下一步是解压缩,它对压缩了的二进制数据进行解码,存储在新的点云对象中,解码了的点云被发送到点云可视化对象中进行实时可视化。voidcloud_cb_(constpcl::PointCloud<pcl::PointXYZRGBA>::ConstPtr&cloud){if(!viewer.wasStopped()){std::stringstreamcompressedData;//存储压缩点云的字节流对象pcl::PointCloud<pcl::PointXYZRGBA>::PtrcloudOut//存储输出点云(newpcl::PointCloud<pcl::PointXYZRGBA>());PointCloudEncoder->encodePointCloud(cloud,compressedData);//压缩点云PointCloudDecoder->decodePointCloud(compressedData,cloudOut);//解压缩点云viewer.showCloud(cloudOut);//可视化解压缩点云}}//在压缩与解压缩过程中,因为设置compressedData为true所以在标准输出上打印出压缩率帧数等信息2.编译并运行该程序利用光盘提供的CMakeLists.txt文件,在CMake中建立工程文件并生成相应的可执行文件,生成执行文件后,就可以运行了,在CMD中键入命令:…>point_cloud_compression.exe可以看到图6-4所示结果,左边为带有RGB纹理信息的实时可视化结果,用户缩放可视化结果可以看到经过压缩后点云进行了重采样,纹理信息有所丢失,但数据量有所减小,在实际应用中需折中取舍。右边则为实时压缩信息输出,可以看出压缩的帧数、点数、压缩率等信息。3.压缩配置文件压缩配置文件为PCL点云编码器定义了参数集,并针对压缩从OpenNI采集器获取的普通点云进行了优化设置。注意,解码对象不需要用参数表示,因为它在解码时检测并获取对应的编码参数配置。下面的压缩配置文件是可用的:LOW_RES_ONLINE_COMPRESSION_WITHOUT_COLOR:分辨率1cm,无颜色,快速在线编码LOW_RES_ONLINE_COMPRESSION_WITH_COLOR:分辨率1cm,有颜色,快速在线编码MED_RES_ONLINE_COMPRESSION_WITHOUT_COLOR:分辨率5mm,无颜色,快速在线编码MED_RES_ONLINE_COMPRESSION_WITH_COLOR:分辨率5mm,有颜色,快速在线编码HIGH_RES_ONLINE_COMPRESSION_WITHOUT_COLOR:分辨率1mm,无颜色,快速在线编码HIGH_RES_ONLINE_COMPRESSION_WITH_COLOR:分辨率1mm,有颜色,快速在线编码333333LOW_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR:分辨率1cm,无颜色,高效离线编码LOW_RES_OFFLINE_COMPRESSION_WITH_COLOR:分辨率1cm,有颜色,高效离线编码MED_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR:分辨率5mm,无颜色,高效离线编码MED_RES_OFFLINE_COMPRESSION_WITH_COLOR:分辨率5mm,有颜色,高效离线编码HIGH_RES_OFFLINE_COMPRESSION_WITHOUT_COLOR:分辨率5mm,无颜色,高效离线编码HIGH_RES_OFFLINE_COMPRESSION_WITH_COLOR:分辨率5mm,有颜色,高效离线编码MANUAL_CONFIGURATION允许为高级参数化进行手工配置。3333334.高级参数化为了能完全控制压缩相关的参数,PointCloudCompression类的构造函数可以在初始化时附加压缩参数。请注意,为了启用高级参数化,compressionProfile_arg参数需要被设置成MANUAL_CONFIGURATION。PointCloudCompression(compression_Profiles_ecompressionProfile_arg,boolshowStatistics_arg,constdoublepointResolution_arg,constdoubleoctreeResolution_arg,booldoVoxelGridDownDownSampling_arg,constunsignedintiFrameRate_arg,booldoColorEncoding_arg,constunsignedcharcolorBitResolution_arg)下面解释高级参数化设置:compressionProfile_arg:为了启用高级参数化,该参数应该被设置成MANUAL_CONFIGURATION。showStatistics_arg:把压缩相关的统计信息打印到标准输出。pointResolution_arg:定义点坐标的编码精度,该参数应该设置成小于传感器精度的一个值。octreeResolution_arg:该参数定义展开了的octree的体素大小,较大的体素分辨率使得压缩更快,但是压缩质量下降,这在较高的帧速率(上传速率)和压缩效率中间进行了折中设置。doVoxelGridDownDownSampling_arg:如果激活该参数,那么只编码分层octree的数据结构,解码对象在体素中心生成点,通过这种方法点云在压缩期间被下采样,同时达到了较高的压缩性能。iFrameRate_arg:点云压缩模式对点云进行差分编码压缩,用这种方法对新引入的点云和之前编码的点云之间的差分进行编码,以便获得最大压缩性能,用这种方法对新引入的点云和之前编码的点云之间的差分进行编码,以便获得最大压缩性能,iFrameRate_arg允许指定数据流中的某一帧速率,在这一速率下传输的点云就不进行差分编码压缩(同视频编码中的I/P帧类似)。doColorEncoding_arg:该选项启用彩色纹理成分编码压缩。colorBitResolution_arg:该参数定义每一个彩色成分编码后所占的位数。5.PCL点云数据流压缩的命令行工具PCL应用程序工具中包含点云流数据压缩命令行工具openni_stream_compression.exe,用户可以查看选项的完整列表(注意:屏幕上的输出可能不同)。该工具可以在安装好的PCL的bin目录下找到。用户可以自行试验看看其强大的功能,具体参看其命令行帮助提示。例如它可以通过网络进行点云压缩传输。为了通过TCP/IP传输压缩点云,可以用下面的命令启动服务器:…>openni_stream-compression.exe–s它会监听6666端口看是否有接入链接请求,用下面的命令开启客户端:…>openni_stream_compression–cSERVER_NAME远程采集到的点云可以通过点云查看工具在本地显示,笔者测试结果如图6-5所示。6.3.2基于octree的空间划分及搜索操作octree是一种用于管理稀疏3D数据的树状数据结构,每个内部节点都正好有8个子节点,本小节中将介绍如何用octree在点云数据中进行空间划分及近邻搜索,特别解释了如何完成“体素内近邻搜索(NeighborswithinVoxelSearch)”、“K近邻搜索(KNearestNeighborSearch)”和“半径内近邻搜索(NeighborswithinRadiusSearch)”。在本书提供光盘的第6章例2文件夹中,打开名为octree_search.cpp的代码文件。1.代码解释说明下面解析打开的源代码,首先定义并实例化一个PointCloud指针对象,并且用随机点集赋值给它。pcl::PointCloud<pcl::PointXYZ>::Ptrcloud(newpcl::PointCloud<pcl::PointXYZ>);//创建点云数据cloud->width=1000;cloud->height=1;cloud->points.resize(cloud->width*cloud->height);for(size_ti=0;i<cloud->points.size();++i)//循环随机产生点坐标值{cloud->points[i].x=1024.0f*rand()/(RAND_MAX+1.0f);cloud->points[i].y=1024.0f*rand()/(RAND_MAX+1.0f);cloud->points[i].z=1024.0f*rand()/(RAND_MAX+1.0f);}然后创建一个octree实例,用设置分辨率进行初始化,该octree用它的叶节点存放点索引向量,该分辨率参数描述最低一级octree的最小体素的尺寸,因此octree的深度是分辨率和点云空间维数的函数,如果知道点云的边界框,应该用defineBoundingBox方法把它分配给octree,然后通过点云指针把所有点增加到octree中。floatresolution=128.0f;pcl::octree::OctreePointCLoudSearch<pcl::PointXYZ>octree(resolution);//初始化octreeoctree.setInputCloud(cloud);//设置输入点云octree.addPointsFromInputCloud();//构建octree一旦PointCloud和octree联系在一起,就能进行搜索操作,这里使用的第一种搜索方法是“体素近邻搜索”,它把查询点所在的体素中其他点的索引作为查询结果返回,结果以点索引向量的形式保存,因此搜索点和搜索结果之间的距离取决于octree的分辨率参数。std::vector<int>pointIdxVec;//存储体素近邻搜索的结果向量if(octree.voxelSearch(searchPoint,pointIdxVec))//执行搜索,返回结果到pointIdxVec{std::cout<<“Neighborswithinvoxelsearchat(”<<searchPoint.x<<““<<searchPoint.y<<““<<searchPoint.z<<“)”<<std::endl;for(size_ti=0;i<pointIdxVec.size();++i)//打印搜索结果点坐标std::cout<<““<<cloud->points[pointIdxVec[i]].x<<““<<cloud->points[pointIdxVec[i]].y<<““<<cloud->points[pointIdxVec[i]].z<<std::endl;}接下来介绍K近邻搜索,本例中K被设置成10,“K近邻搜索”方法把搜索结果写到两个分开的向量中,第一个pointIdxNKNSearch包含搜索结果(结果点的索引的向量),第二个向量保存相应的搜索点和近邻之间的距离平方。//K近邻搜索intK=10;std::vector<int>pointIdxNKNSearch;//存储k近邻搜索点索引结果std::vector<float>pointNKNSquaredDistance;std::cout<<“Knearestneighborsearchat(“<<searchPoint.x<<““<<searchPoint.y<<““<<searchPoint.z<<“)withK=”<<K<<std::endl;if(octree.nearestKSearch(searchPoint,K,pointIdxNKNSearch,pointNKNSquaredDistance)>0){for(size_ti=0;i<pointIdxNKNSearch.size();++i)//打印搜索结果点坐标Std::cout<<““<<cloud->points[pointIdxNKNSearch[i]].x<<““<<cloud->points[pointIdxNKNSearch[i]].y<<““<<cloud->points[pointIdxNKNSearch[i]].z<<“(squareddistance:”<<pointNKNSquaredDistance[i]<<“)”<<std::endl;}“半径内近邻搜索”原理和“K近邻搜索”类似,它的搜索结果被写入两个分开的向量中,这两个向量分别存储结果点的索引和对应的距离平方。//半径内近邻搜索std::vector<int>pointIdxRadiusSearch;std::vector<float>pointRadiusSquaredDistance;floatradius=256.0f*rand()/(RAND_MAX+1.0f);std::cout<<“Neighborswithinradiussearchat(”<<searchPoint.x<<““<<searchPoint.y<<““<<searchPoint.z<<“)withradius=”<<radius<<std::endl;if(octree.radiusSearch(searchPoint,radius,pointIdxRadiusSearch,pointRadiusSquaredDistance)>0){for(size_ti=0;i<pointIdxRadiusSearch.size();++i)Std::cout<<““<<cloud->points[pointIdxRadiusSearch[i]].x<<““<<cloud->points[pointIdxRadiusSearch[i]].y<<““<<cloud->points[pointIdxRadiusSearch[i]].z<<“(squareddistance:”<<pointRadiusSquaredDistance[i]<<“)”<<std::endl;}2.编译并运行该程序利用光盘提供的CMakeLists.txt文件,在CMake中建立工程文件,并生成相应的可执行文件,生成执行文件后就可以运行了,在CMD中键入命令:…>octreesearch.exe运行结果如图6-6所示,分别打印出不同搜索方式的输出结果。3.Octree部分类关键点说明PCLoctree组件提供了几个octree类型。它们各自的叶节点特征基本上是不同的。OctreePointCloudPointVector(等于OctreePointCloud):该octree能够保存每一个叶节点上的点索引列。OctreePointCloudSinglePoint:该octree类仅仅保存每一个叶节点上的单个点索引。仅仅保存最后分配给叶节点的点索引。OctreePointCloudOccupancy:该octree不存储它的叶节点上的任何点信息。它能用于空间填充情况检查。OctreePointCloudDensity:该octree存储每一个叶节点体素中点的数目。它可以进行空间点集密集程度查询。如果需要高频率创建octree,请参看octree双缓冲技术实现(Octree2BufBase类)。该类在内存中同时保存了两个类似的octree对象。除了搜索操作之外也可以用于空间变化检测。此外,高级内存管理减少了octree建立过程中的内存分配和释放操作。双缓冲技术对octree的实现可以通过设置模板参数“OctreeT”实例化不同的OctreePointCloud类。所有的octree都支持octree结构和octree内容的串行化和反串行化。6.3.3无序点云数据集的空间变化检测octree是一种用于管理稀疏3D数据的树状数据结构,本小节中将介绍如何利用octree实现用于多个无序点云之间的空间变化检测,这些点云可能在尺寸、分辨率、密度和点顺序等方面有所差异。通过递归地比较octree的树结构,可以鉴定出由octree产生的体素组成之间的区别所代表的空间变化,此外还解释了如何使用PCL的octree“双缓冲”技术,以便能实时地探测多个点云之间的空间组成差异。在本书提供光盘的第6章例3文件夹中,打开名为octree_change_detection.cpp的代码文件。1.代码解释说明首先实例化OctreePointCloudChangeDetector类,并定义它的体素分辨率。srand((unsignedint)time(NULL));floatresolution=32.0f;//八叉树分辨率即体素的大小//初始化空间变化检测对象pcl::octree::OctreeP

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论