pcl通過積分圖來進行法線預測

首先,我們來看一下什麼是積分圖,我查了一下wiki,發現它的定義是這樣的。

A summed area table is a data structure and algorithm for quickly and efficiently generating the sum of values in a rectangular subset of a grid. In the image processing domain, it is also known as an integral image. It was introduced to computer graphics in 1984 by Frank Crow for use with mipmaps. In computer vision it was popularized by Lewis[1] and then given the name "integral image" and prominently used within theViola–Jones object detection framework in 2001. Historically, this principle is very well known in the study of multi-dimensional probability distribution functions, namely in computing 2D (or ND) probabilities (area under the probability distribution) from the respective cumulative distribution functions.[2]

一個加法區域表是一個快速計算一個柵格矩形的和的快速有效的數據結構和算法。在圖像處理領域,它也叫積分圖。/歷史我就不說了/ 積分圖在多維概率分佈用得比較多。

接着看

As the name suggests, the value at any point (xy) in the summed area table is just the sum of all the pixels above and to the left of (xy), inclusive:[3][4]

顧名思義,點(x,y)的像素值是它上面和左邊所有的像素值的和。

此外,加法區域表在圖像裏面的某個通道(如RGB圖像有3個通道,R,G,B這3個顏色個表示一個通道)的計算是很高效的,下面的這個公式就簡單的就行了解釋。

Moreover, the summed area table can be computed efficiently in a single pass over the image, using the fact that the value in the summed area table at (xy) is just:

Once the summed area table has been computed, the task of evaluating the intensities over any rectangular area requires only four array references. This allows for a constant calculation time that is independent of the size of the rectangular area. That is, using the notation in the figure at right, having A=(x0, y0), B=(x1, y0), C=(x0, y1) and D=(x1, y1), the sum of i(x,y) over the rectangle spanned by A, B,C and D is:

一旦加法區域計算完成之後,評估然後矩形區域的強度只需要引用4個數組。這使得我們可以得到一個不變的運算次數,和矩形的面積無關。其實那4個數組就是等號右邊的那幾個被加數,如果不這樣的話,越往下,越往右的點的計算次數就越來越大,會大大超過4次。接下去是一張圖,不過我們這次算的不是I(D)而是i(x,y)

明白了,以後我們接下去看。

先寫一個 normal_estimation_using_integral_images.cpp的cpp文件

     #include <pcl/io/io.h>
     #include <pcl/io/pcd_io.h>
     #include <pcl/features/integral_image_normal.h>
     #include <pcl/visualization/cloud_viewer.h>

     int
     main ()
     {
             // load point cloud
             pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
             pcl::io::loadPCDFile ("table_scene_mug_stereo_textured.pcd", *cloud);

             // estimate normals
             pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);

             pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
             ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
             ne.setMaxDepthChangeFactor(0.02f);
             ne.setNormalSmoothingSize(10.0f);
             ne.setInputCloud(cloud);
             ne.compute(*normals);

             // visualize normals
             pcl::visualization::PCLVisualizer viewer("PCL Viewer");
             viewer.setBackgroundColor (0.0, 0.0, 0.5);
             viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, normals);

             while (!viewer.wasStopped ())
             {
               viewer.spinOnce ();
             }
             return 0;
     }

第一步先加載了一個點雲文件

pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPCDFile ("table_scene_mug_stereo_textured.pcd", *cloud);

接下去我們建了一個類來預測與計算法線

// estimate normals
pcl::PointCloud<pcl::Normal>::Ptr normals (new pcl::PointCloud<pcl::Normal>);

pcl::IntegralImageNormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setNormalEstimationMethod (ne.AVERAGE_3D_GRADIENT);
ne.setMaxDepthChangeFactor(0.02f);
ne.setNormalSmoothingSize(10.0f);
ne.setInputCloud(cloud);
ne.compute(*normals);

其中有下面一些預測方法

enum NormalEstimationMethod
{
  COVARIANCE_MATRIX,
  AVERAGE_3D_GRADIENT,
  AVERAGE_DEPTH_CHANGE
};

這個COVARIANCE_MATRIX模型,從最近鄰的協方差矩陣創建了9個積分圖去計算一個點的法線。AVERAGE_3D_GRADIENT模型創建了6個積分圖去計算3D梯度裏面豎直和水平方向的光滑部分,同時利用兩個梯度的卷積來計算法線。AVERAGE_DEPTH_CHANGE模型創造了一個單一的積分圖,從平均深度的變化中來計算法線。

最終我們使他可視化。

// visualize normals
pcl::visualization::PCLVisualizer viewer("PCL Viewer");
viewer.setBackgroundColor (0.0, 0.0, 0.5);
viewer.addPointCloudNormals<pcl::PointXYZ,pcl::Normal>(cloud, normals);

while (!viewer.wasStopped ())
{
  viewer.spinOnce ();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章