1. 程式人生 > >PCL—關鍵點檢測(rangeImage)低層次點雲處理

PCL—關鍵點檢測(rangeImage)低層次點雲處理

數據結構 關系 n-1 -a 平面 邊緣提取 bubuko 數據 方式

博客轉載自:http://www.cnblogs.com/ironstark/p/5046479.html

關鍵點又稱為感興趣的點,是低層次視覺通往高層次視覺的捷徑,抑或是高層次感知對低層次處理手段的妥協。

                                      ——三維視覺關鍵點檢測

1.關鍵點,線,面

關鍵點 = 特征點;

關鍵線 = 邊緣;

關鍵面 = foreground;

上述三個概念在信息學中幾乎占據了統治地位。比如1維的函數(信號),有各種手段去得到某個所謂的關鍵點,有極值點,拐點...二維的圖像,特征點提取算法是標定算法的核心(harris),邊緣提取算法更是備受矚目(canny,LOG.....),當然,對二維的圖像也有區域所謂的前景分割算法用於提取感興趣的區域,但那屬於較高層次的視覺,本文不討論。 由此可以推斷,三維視覺應該同時具備:關鍵點,關鍵線,關鍵面三種算法。本質上,關鍵面算法就是我們之前一文中討論的分割算法(三維點雲不是實心的)。關於關鍵點更多的信息可以參考:特征檢測

ok,在這裏我們了解到了,要在n維信息中提取n-1維信息是簡單的,但n-2維信息會比n-1維要不穩定或者復雜的多。很容易想象,圖像的邊緣處理算法所得到的結果一般大同小異,但關鍵點提取算法的結果可以是千差萬別的。主要原因是降維過大後,特征的定義很模糊,很難描述清楚對一幅圖像來說,到底怎樣的點才是關鍵點。所以,對3維點雲來說,關鍵點的描述就更難了。點雲也有1維邊緣檢測算法,本文不做討論。單說說關鍵點提取。

2.來自點雲的降維打擊

圖像的Harris角點算子將圖像的關鍵點定義為角點。角點也就是物體邊緣的交點,harris算子利用角點在兩個方向的灰度協方差矩陣響應都很大,來定義角點。既然關鍵點在二維圖像中已經被成功定義且使用了,看來在三維點雲中可以沿用二維圖像的定義...不過今天要講的是另外一種思路,簡單粗暴,直接把三維的點雲投射成二維的圖像不就好了。這種投射方法叫做range_image.

首先放上一張range_imge和點雲圖像的合照:

技術分享圖片

看起來像個眼睛的那玩意就是range_image. 至於它為什麽像個眼睛,就要從它的出生開始說起了。三維點雲有多種采集方式,最為著名的是結構光,飛秒相機,雙目視覺。簡而言之,采集都離不開相機。用相機拍照當然就存在相機的光心坐標原點 Oc 以及主光軸方向 Z. 從這個點,有一種辦法可以將三維數據映射到2維平面上。首先,將某點到光心Oc的距離映射成深度圖的灰度或顏色(灰度只有256級但顏色卻可接近連續變化)。除此之外,再定義一下怎樣將點雲映射到圖像的橫縱坐標上就可以了。

任意一點都要和光心進行連線.....這麽聽起來很熟悉....好像有點像球坐標的意思。球坐標長下面這張圖這樣。

技術分享圖片

技術分享圖片

深度圖中的橫,縱坐標實際上是a和phi,如果要保證沿著場景中某條直線移動,a線性變化phi卻先增大後減小。這也就造成了深度圖像一個眼睛一樣。但這並不妨礙什麽,phi沒有定義的地方可以使用深度無限大來代替。

將點雲轉成深度圖,只需要確定一個直角坐標系,角分辨率,a範圍,phi範圍即可。畢竟這只是一個直角坐標轉球坐標的工作而已。

這樣做顯然是有好處的,首先,這是一種除了八叉樹,kd_tree之外,能夠將點雲的空間關系表達出來的手段。每個點雲都有了橫,縱,深,三個坐標,並且這種坐標原點的設定方式,在理論上是不會存在幹涉的(從原點出發的一條線理論上不會遇到多余1個點)。於是點雲的空間關系就自然的被編碼與深度圖中。

顯然,圖像中的關鍵點檢測算子就可以被移植到點雲特征點求取中來了。

3.基於PCL的點雲-深度圖轉換

//rangeImage也是PCL的基本數據結構
pcl::RangeImage rangeImage;
//角分辨率
float angularResolution = (float) (  1.0f * (M_PI/180.0f));  //   1.0 degree in radians
//phi可以取360°
  float maxAngleWidth     = (float) (360.0f * (M_PI/180.0f));  // 360.0 degree in radians
//a取180°
  float maxAngleHeight    = (float) (180.0f * (M_PI/180.0f));  // 180.0 degree in radians
//半圓掃一圈就是整個圖像了

//傳感器朝向
  Eigen::Affine3f sensorPose = (Eigen::Affine3f)Eigen::Translation3f(0.0f, 0.0f, 0.0f);
//除了三維相機模式還可以選結構光模式
  pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
//noise level表示的是容差率,因為1°X1°的空間內很可能不止一個點,noise level = 0則表示去最近點的距離作為像素值,如果=0.05則表示在最近點及其後5cm範圍內求個平均距離
  float noiseLevel=0.00;
//minRange表示深度最小值,如果=0則表示取1°X1°的空間內最遠點,近的都忽略
  float minRange = 0.0f;
//bordersieze表示圖像周邊點  
  int borderSize = 1;
//基本數據結構直接打印是ok的
  std::cout << rangeImage << "\n";

PCL—關鍵點檢測(rangeImage)低層次點雲處理