1. 程式人生 > >點特徵直方圖(PFH)描述(Point Feature Histograms (PFH) descriptors)

點特徵直方圖(PFH)描述(Point Feature Histograms (PFH) descriptors)

#點特徵直方圖(PFH)描述符 隨著點特徵表示的進行,曲面法線和曲率估計在它們圍繞特定點的幾何圖形的表示中是相當基本的。雖然計算起來非常快速和容易,但它們不能捕獲太多的細節,因為它們只能用幾個值來逼近點的k鄰域的幾何。直接的結果是,大多數場景將包含許多具有相同或非常相似的特徵值的點,從而降低了它們的資訊特徵。

為了簡單起見,本教程介紹了一系列建立PFH(點特徵直方圖)的3D特徵描述符,展示了它們的理論優勢,並從PCL的角度討論了實現細節。作為先決條件,請繼續閱讀PointCloud教程中的估算曲面法線,因為PFH簽名既依賴於 xyz 3D data,也依賴於曲面法線

#理論引入 PFH公式的目標是通過使用值的多維直方圖推廣點周圍的平均曲率來編碼點的k鄰域幾何特性。這個高度空間超空間為特徵表示提供了資訊簽名,對於下面的表面的6D姿態是不變的,並且可以很好地處理鄰域中存在的不同取樣密度或噪聲水平。

點特徵直方圖表示基於k鄰域中的點與其估計的表面法線之間的關係。簡而言之,它試圖通過考慮所估計的法線的方向之間的所有相互作用來儘可能最好地捕獲取樣的表面變化。由此產生的超空間依賴於每個點處的表面法線估計的質量。

下圖給出了查詢點(p_q)的PFH計算的影響區域圖,用紅色標記,放置在半徑為r的圓形(sphere in 3D)中,所有k個鄰居(距離小於半徑r)完全互連在一個網格中。最終PFH描述符被計算為鄰域中所有點對之間關係的直方圖,因此具有的計算複雜度為 O(k^2) 。

_images/pfh_diagram.png

為了計算兩個點之間的相對差P_I和 p_j與它們相關聯的法線你和n_j,我們在點(參見下圖)中的一個限定固定的座標系。

{\ mathsf u} =&\ boldsymbol {n} _s \ {\ mathsf v} =&{\ mathsf u} \ times \ frac {(\ boldsymbol {p} _t- \ boldsymbol {p} _s)} {{ \ | \ boldssmbol {p} _t- \ boldsymbol {p} _s \ |} _ {2}} \ {\ mathsf w} =&{\ mathsf u} \ times {\ mathsf v}

_images / pfh_frame.png

使用上述UVW幀,兩個法線之間的差 N_S,並N_T可以如下表示為一組的角度的特點:

\ alpha {\ mathsf v} \ cdot \ boldsymbol {n} _t \ \ phi&= {\ mathsf u} \ cdot \ frac {(\ boldsymbol {p} _t - \ boldsymbol {p} _s)} { d} \ \ theta&= \ arctan({\ mathsf w} \ cdot \ boldsymbol {n} _t,{\ mathsf u} \ cdot \ boldsymbol {n} _t)\

其中d是兩個點之間的歐幾里得距離 \ boldsymbol {P} _s和\ boldsymbol {P} _t, d = {\ | \ boldsymbol {P} _t- \ boldsymbol {P} _s \ |} _2。\ langle \ alpha,\ phi,\ theta,d \ rangle對於k鄰域中的每一對兩點計算四元組,因此將兩點和它們的法線的12個值(xyz和正常資訊)減少到4。

要估算一對點的PFH四聯體,請使用:


computePairFeatures (const Eigen::Vector4f &p1, const Eigen::Vector4f &n1,

                    const Eigen::Vector4f &p2, const Eigen::Vector4f &n2,

                    float &f1, float &f2, float &f3, float &f4);

有關更多詳細資訊,請參閱API文件。

為了建立查詢點的最終PFH表示,所有四元組的集合被組合成一個直方圖。合併過程將每個特徵的值範圍劃分為b個子範圍,並計算每個子範圍內出現的次數。由於上述四個特徵中的三個是法線之間角度的測量值,所以它們的值可以很容易地在三角圓上歸一化到相同的間隔。裝倉示例是將每個特徵區間劃分為相同數目的相同部分,因此建立一個直方圖 b^4在完全相關的空間中的垃圾箱。在這個空間中,直方圖倉增量對應於其所有4個特徵具有特定值的點。下圖給出了雲中不同點的點特徵直方圖表示的例子。

在某些情況下,第四個特徵d對於2.5D資料集並不具有極端重要性,通常在機器人中獲取,因為相鄰點之間的距離從視點增加。因此,對於區域性點密度影響該特徵維度的掃描省略d已被證明是有益的。

_images/example_pfhs.jpg

    注意:
    有關更多資訊和數學推導(包括不同表面幾何形狀的PFH特徵分析),請參閱[Rusu論文](http://pointclouds.org/documentation/tutorials/how_features_work.php#rusudissertation)。

#估算PFH功能 點特徵直方圖是作為pcl_features庫的一部分在PCL中實現的。

預設的PFH實現使用5個binning細分(例如,四個特徵值中的每一個將使用它的值間隔中的這個多個bin),並且不包括距離(如上所述 - 雖然computePairFeatures方法可以由使用者呼叫如果需要,也可以獲得距離),從而得到5^3浮點值的125位元組陣列。這些儲存在pcl::PFHSignature125點型別中。

下面的程式碼片段將為輸入資料集中的所有點估計一組PFH特徵。

#include <pcl/point_types.h>
#include <pcl/features/pfh.h>

{
  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
  pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal> ());

  ... read, pass in or create a point cloud with normals ...
  ... (note: you can create a single PointCloud<PointNormal> if you want) ...

  // Create the PFH estimation class, and pass the input dataset+normals to it
  pcl::PFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::PFHSignature125> pfh;
  pfh.setInputCloud (cloud);
  pfh.setInputNormals (normals);
  // alternatively, if cloud is of tpe PointNormal, do pfh.setInputNormals (cloud);

  // Create an empty kdtree representation, and pass it to the PFH estimation object.
  // Its content will be filled inside the object, based on the given input dataset (as no other search surface is given).
  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ> ());
  //pcl::KdTreeFLANN<pcl::PointXYZ>::Ptr tree (new pcl::KdTreeFLANN<pcl::PointXYZ> ()); -- older call for PCL 1.5-
  pfh.setSearchMethod (tree);

  // Output datasets
  pcl::PointCloud<pcl::PFHSignature125>::Ptr pfhs (new pcl::PointCloud<pcl::PFHSignature125> ());

  // Use all neighbors in a sphere of radius 5cm
  // IMPORTANT: the radius used here has to be larger than the radius used to estimate the surface normals!!!
  pfh.setRadiusSearch (0.05);

  // Compute the features
  pfh.compute (*pfhs);

  // pfhs->points.size () should have the same size as the input cloud->points.size ()*
}

來自PFHEstimation類的實際計算呼叫在內部不做任何事情,但是:

for each point p in cloud P

  1. get the nearest neighbors of p

  2. for each pair of neighbors, compute the three angular values

  3. bin all the results in an output histogram

要計算k鄰域中的單個PFH表示,請使用:

computePointPFHSignature (const pcl::PointCloud<PointInT> &cloud,
                          const pcl::PointCloud<PointNT> &normals,
                          const std::vector<int> &indices,
                          int nr_split,
                          Eigen::VectorXf &pfh_histogram);

其中cloud是包含點的輸入點雲,normals是包含法線的輸入點雲(如果PointInT=PointNT=PointNorm,則可以等於雲 ),indices代表來自雲的k個最近鄰居的集合,nr_split是用於每個特徵間隔的裝倉過程的細分數目,而pfh_histogram是作為浮點值陣列的輸出結果直方圖。

   注意:
   出於效率原因,`PFHEstimation`中的計算方法不檢查法線是否包含`NaN`或`無限值`。將這些值傳遞給`compute()`會導致未定義的輸出。建議檢查法線,至少在加工鏈的設計或設定引數時。這可以通過在呼叫`compute()`之前插入以下程式碼來完成:
for (int i = 0; i < normals->points.size(); i++)
{
  if (!pcl::isFinite<pcl::Normal>(normals->points[i]))
  {
    PCL_WARN("normals[%d] is not finite\n", i);
  }
}
   在生產程式碼中,應該設定預處理步驟和引數,使法線是有限的或產生錯誤。