PCL中RANSAC模型的使用

RANSAC算法是什麼

        RANSAC算法於1981年由Fischler和Bolles提出,全程是RANdom SAmple Consensus,一般中文翻譯爲“隨機抽樣一致性算法”,它是一個迭代算法,主要用於從包含外點(outliers,可理解爲噪聲)的數據集中估計數學模型的參數。RANSAC算法有兩個假設,第一個是假定所有的數據都是由內點和外點組成,內點可由特定參數的模型所表示,而外點則在任何情況下都不能滿足由內點的模型,另外一個必要的假設是存在程序可以從數據中最優的估計出所選擇模型的參數。

RANSAC算法迭代過程

        RANSAC算法的輸入需要數據集和可以表示數據集的參數化模型,以及一些置信參數。RANSAC算法通過迭代的從原始數據裏選擇一個隨機性的子集來得到最終結果,假定子數據集爲內點,然後通過以下步驟來驗證這個假設:

  1. 由假定的內點擬合出一個數據模型,即根據內點重構模型的所有自由參數;
  2. 所有其他的數據在擬合出的模型上進行驗證,假如某個點符合所得到的模型,那麼這個點就被認爲也是內點;
  3. 如果有足夠多的點被認爲是內點,則估計的模型就相當好;
  4. 然後根據所有的內點重新估計模型,因爲之前的模型只是從初始的內點估計出來的;
  5. 最後通過內點和模型的誤差來評估整個模型的好壞。

這個過程重複固定次數,每次都會產生一個模型,假如太少的點被歸類爲內點,則模型被丟棄,反之則得到一個改進的模型以及測量誤差,如果測量誤差低於上次保存的模型的話,就保留改進的模型。

RANSAC算法優缺點

        RANSAC算法的優點是能夠對模型參數進行魯棒估計,也就是說,即使數據集中存在大量的異常值,它也可以高精度地估計參數。RANSAC的缺點是計算這些參數所需的時間沒有上限,當計算的迭代次數有限時,得到的解可能不是最優解,甚至可能不是一個很好地適合數據的解。所以RANSAC提供了一個折衷方案:通過計算更多的迭代次數,可以增加產生合理模型的概率。RANSAC的另一個缺點是它需要設置特定的問題域,即對於某個特定的數據集,RANSAC只能估計出一個模型,如果原始數據裏存在兩個(或多個)模型,RANSAC可能無法找到其中一個。

RANSAC算法簡單示例

        RANSAC算法應用於一個二維的數據集上(來源維基百科),左邊圖片顯示了一個包含內點和外點的數據集,右邊圖片中所有的外點爲紅色,內點爲藍色,藍色的線爲應用RANSAC算法生成的模型,這個示例是要在原始數據中擬合出一條直線,從右圖中可以看到模型與數據匹配的相當好。

 PCL中RANSAC算法使用

        使用PCL中的RANSAC算法,需要包含ransac.h頭文件,在此示例中,需要指定平面和球兩個模型,因此同時加入了平面和球模型相關的頭文件,如下所示:

#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/sample_consensus/sac_model_sphere.h>

首先,定義所需要的模型,這裏定義了兩個,第一個爲球模型,第二個爲平面模型:

pcl::SampleConsensusModelSphere<pcl::PointXYZ>::Ptr
    model_s(new pcl::SampleConsensusModelSphere<pcl::PointXYZ> (cloud));
pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr
    model_p (new pcl::SampleConsensusModelPlane<pcl::PointXYZ> (cloud));

其次,使用RandomSampleConsensus實例化RANSAC算法,inliers用於存儲內點的索引,傳入所要擬合的模型(這裏爲平面或球模型),計算並得到內點

std::vector<int> inliers;
pcl::RandomSampleConsensus<pcl::PointXYZ> ransac (model_p);
ransac.setDistanceThreshold (.01);
ransac.computeModel();
ransac.getInliers(inliers);

在本示例中,程序中的數據集如下所示,兩張圖爲同一個點雲的不同角度,其中有1/5的數據爲隨意放置的,從圖中可以看到,點雲並不是很規整,幷包含一些外點在裏面

 RandomSampleConsensus輸入平面模型可得結果如下,可以看到不符合平面模型的外點被移除,而平面的內點組成了一個平面:

未應用RANSAC算法的球狀點雲包含部分外點如以下左圖所示,使用球體模型應用RANSAC算法後官方示例如下右圖所示,在此需要注意的是,PCL官方示例中給出的圖是正確的,但是在Windows上運行時,原始點云爲一個正方體,不是球體,然後應用RANSAC後只能得到少數幾個點,原因是官方的示例代碼在windows上時,rand()產生的值在[0,32767],並不是官方文檔中說的[0,1],所以最後得出的是一個正方體,修改代碼生成合適的球體即可應用PCL的RANSAC算法,結果如下:

 

開發環境及程序

    開發環境:VS2015 & PCL1.8.1

    PCL 頭及庫文件配置

Include:
$(PCL_ROOT);
$(PCL_ROOT)\include\pcl-1.8;
$(PCL_ROOT)\3rdParty\Eigen\eigen3;
$(PCL_ROOT)\3rdParty\FLANN\include;
$(PCL_ROOT)\3rdParty\VTK\include\vtk-8.0;
$(PCL_ROOT)\3rdParty\Boost\include\boost-1_64;
 
lib:
$(PCL_ROOT)\lib\*.lib
$(PCL_ROOT)\3rdParty\VTK\lib\*.lib
$(PCL_ROOT)\3rdParty\FLANN\lib\*.lib
$(PCL_ROOT)\3rdParty\Boost\lib\*.lib

工程及源碼地址: https://github.com/yazhouzheng/RANSACInPCL.git

參考

    1. http://pointclouds.org/documentation/tutorials/random_sample_consensus.php 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章