pcl 無序點雲資料空間變化檢測
- 原理
- Code
- Result
原理
octree是一種管理稀疏3D資料的樹狀結構,利用octree實作多個無序點雲之間的空間變化檢測,這些點雲可能在尺寸。分辨率 密度,和點順序等方面有所差異,通過遞歸的比較octree的樹結構,可以鑒定出由octree産生的體素組成的差別所代表的空間變化,并且通過octree的“雙緩沖”技術,可以實時的探測多個點雲之間的空間組成的差異。
對無序點雲在空間變化上的檢測,其實是對前後兩幅點雲在八叉樹結構下的差異檢測。是以我們要首先載入一個原始點雲,并生成第一個八叉樹結構;然後切緩沖,載入第二個點雲,生成第二個八叉樹結構;最後進行比較,如果有一些葉子結點在第二個八叉樹上,但是不在第一個八叉樹上,那麼就認為這些葉子節點内的點是空間上變化多出來的點。
Code
=====================================================
#include <pcl/point_cloud.h>
#include <pcl/octree/octree.h>
#include <iostream>
#include <vector>
#include <ctime>
包含的頭檔案
=====================================================
//建立時間随機種子 取随機數用的
srand ((unsigned int) time (NULL));
//聲明一個點雲 A 指針 并配置設定空間
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudA (new pcl::PointCloud<pcl::PointXYZ> );
//定義點雲大小 點雲個數128個,無序
cloudA->width =128;
cloudA->height =1;
cloudA->points.resize (cloudA->width *cloudA->height);
//循環給點雲指派 通過 随機數 點雲的坐标 0-64
for (size_t i=0; i<cloudA->points.size (); ++i)
{
cloudA->points[i].x =64.0f* rand () / (RAND_MAX +1.0f);
cloudA->points[i].y =64.0f* rand () / (RAND_MAX +1.0f);
cloudA->points[i].z =64.0f* rand () / (RAND_MAX +1.0f);
}
建立一個點雲 cloudA
個數 128個 x,y,z的坐标 0-64 取随機值
=====================================================
/* 設定分辨率 描述的是最低一級 八叉樹 的 最小體素 的 尺寸*/
float resolution =32.0f;
/* 建構 八叉樹 變化 檢測 的 類 并設定 分辨率 */
pcl::octree::OctreePointCloudChangeDetector<pcl::PointXYZ>octree (resolution);
建構 八叉樹 變化 檢測 的 類 并設定 分辨率
=====================================================
/* 指派八叉樹的 點雲 */
octree.setInputCloud (cloudA);//設定輸入的點雲
octree.addPointsFromInputCloud ();//将輸入的點雲添加到八叉樹
将 cloudA 輸入 八叉樹 ,建構其資料結構 将其作為基礎點雲
後面可檢測比其多的點雲多的點。但是不能檢測 第二個點雲比其少的點
=====================================================
/*交換八叉樹緩存,但是cloudA對應的八叉樹仍在記憶體中*/
octree.switchBuffers ();
點雲 cloudA 是 參考點雲 ,用其建立的八叉樹對象 描述它的空間分布
OctreePointCloudChangeDetector繼承自 Octree2BufBase 類,該類允許同時在記憶體中儲存和管理兩個八叉樹
它應用了記憶體池,重複利用已經配置設定的節點對象,減少記憶體配置設定和釋放操作
通過通路octree.switchBuffers () 重置了八叉樹對象的緩存區,但把之前的八叉樹仍然留着緩存中
=====================================================
//聲明一個點雲 B 指針 并配置設定空間
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudB (new pcl::PointCloud<pcl::PointXYZ> );
//定義點雲大小 點雲個數128個,無序
cloudB->width =128;
cloudB->height =1;
cloudB->points.resize (cloudB->width *cloudB->height);
//循環給點雲指派 通過 随機數 點雲的坐标 0-64
for (size_t i=0; i<cloudB->points.size (); ++i)
{
cloudB->points[i].x =90.0f* rand () / (RAND_MAX +1.0f);
cloudB->points[i].y =90.0f* rand () / (RAND_MAX +1.0f);
cloudB->points[i].z =90.0f* rand () / (RAND_MAX +1.0f);
}
聲明一個點雲 B 指針 并配置設定空間
個數 128個 x,y,z的坐标 0-90 取随機值
範圍比A 大一點 ,容易有效果
=====================================================
/*聲明 B 比 A 多 出 的點雲 的索引值 儲存 向量*/
std::vector<int>newPointIdxVector;
/* 得到B比A 多出來的 索引值 注意 B 比 A 少的 不會得到 */
octree.getPointIndicesFromNewVoxels (newPointIdxVector);
通過 函數 getPointIndicesFromNewVoxels 得 到 B比A 多出來的 索引值
=====================================================
// 終端列印 B 比 A 多出 來的 點雲
std::cout<<"Output from getPointIndicesFromNewVoxels:"<<std::endl;
for (size_t i=0; i<newPointIdxVector.size (); ++i)
std::cout<<i<<"# Index:"<<newPointIdxVector[i]
<<" Point:"<<cloudB->points[newPointIdxVector[i]].x <<" "
<<cloudB->points[newPointIdxVector[i]].y <<" "
<<cloudB->points[newPointIdxVector[i]].z <<std::endl;
終端列印 B 比 A 多出 來的 點雲
=====================================================
//聲明一個點雲 C 指針 并配置設定空間
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudC (new pcl::PointCloud<pcl::PointXYZ> );
//定義點雲大小 點雲個數上面計算的 B 比 A 多出的 個,無序
cloudC->width =newPointIdxVector.size ();
cloudC->height =1;
cloudC->points.resize (cloudC->width *cloudC->height);
for(size_t i=0;i<newPointIdxVector.size ();++i)
{
cloudC->points[i]=cloudB->points[newPointIdxVector[i]];
}
建立一個點雲C 來儲存 B比A 多出來的點
=====================================================
//可視化子產品
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewwe"));//建立指針viewer
viewer->initCameraParameters();//初始化相機參數
添加可視子產品 來 把 點雲顯示出來
=====================================================
int v1(0);//第一個視窗的參數
viewer->createViewPort(0.0,0.0,0.33,1,v1); //設定第一個視窗的大小,位于螢幕左側
viewer->setBackgroundColor(0,0,0,v1);//background of first port
viewer->addText("cloudA",10,10,"cloudA",v1);//好像是一個便簽
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color1(cloudA,255,0,0);//設定第一個點雲的顔色
viewer->addPointCloud<pcl::PointXYZ>(cloudA,single_color1,"cloudA",v1);//顯示第一個點雲
把 點雲A 顯示為 紅色
=====================================================
int v2(0);//第一個視窗的參數
viewer->createViewPort(0.33,0,0.66,1,v2);//設定第二個視窗的大小,位于螢幕右側
viewer->setBackgroundColor(0,0,0,v2);//background of second port
viewer->addText("cloudB",10,9,"cloudB",v2);//輸出一行文字
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color2(cloudB,0,255,0);//設定第二個點雲的顔色
viewer->addPointCloud<pcl::PointXYZ>(cloudB,single_color2,"simple_cloud2",v2);//顯示第二個點雲
第二個視窗 點雲 B 顯示 為綠色
=====================================================
//第三個點雲視窗
int v3(0);//第三個視窗的參數
viewer->createViewPort(0.66,0,1,1,v3);//視窗大小
viewer->setBackgroundColor(0,0,0,v3);//背景顔色
viewer->addText("cloud_result",10,8,"cloud_result",v3);//好像是一個便簽
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color3(cloudC,255,255,255);//點雲顔色
viewer->addPointCloud<pcl::PointXYZ>(cloudA,single_color1,"cloud1",v3);//顯示點雲
viewer->addPointCloud<pcl::PointXYZ>(cloudB,single_color2,"cloud2",v3);//顯示點雲
viewer->addPointCloud<pcl::PointXYZ>(cloudC,single_color3,"cloud3",v3);//顯示點雲
viewer->addCoordinateSystem(2);//添加坐标系
viewer->spin();
第三個視窗将 點雲A、B、C 顯示在一起。來看下整體效果
=====================================================
Result
終端列印的 B 比A 多出的 點雲
點雲顯示的點
左邊為點雲A ,中間為點雲B
右邊為三個點雲的組合;
紅色的是A點雲有B點雲沒有的;綠色為A和B共有的;白色為B比A 多的。