《點云庫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

提交評論