1. 程式人生 > >【視覺-立體視覺】立體匹配幾種演算法效能比較

【視覺-立體視覺】立體匹配幾種演算法效能比較

OpenCV三種立體匹配求視差圖演算法總結

對OpenCV中涉及的三種立體匹配演算法進行程式碼及各自優缺點總結:

首先我們看一下BM演算法:

該演算法程式碼:

  1. CvStereoBMState *BMState = cvCreateStereoBMState();  
  2. int SADWindowSize=15;   
  3.  BMState->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;  
  4.  BMState->minDisparity = 0;  
  5.  BMState->numberOfDisparities = 32;  
  6.  BMState->textureThreshold = 10;  
  7.  BMState->uniquenessRatio = 15;  
  8.  BMState->speckleWindowSize = 100;  
  9.  BMState->speckleRange = 32;  
  10.  BMState->disp12MaxDiff = 1;  
  11.  cvFindStereoCorrespondenceBM( left, right, left_disp_,BMState);  
  12.    cvNormalize( left_disp_, left_vdisp, 0, 256, CV_MINMAX );  

其中minDisparity是控制匹配搜尋的第一個引數,代表了匹配搜蘇從哪裡開始,numberOfDisparities表示最大搜索視差數uniquenessRatio表示匹配功能函式,這三個引數比較重要,可以根據實驗給予引數值。

該方法速度最快,一副320*240的灰度圖匹配時間為31ms,視差圖如下。

第二種方法是SGBM方法這是OpenCV的一種新演算法:

  1. cv::StereoSGBM sgbm;  
  2.         sgbm.preFilterCap = 63;  
  3.         int SADWindowSize=11;   
  4.         int cn = 1;  
  5.         sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;  
  6.         sgbm.P1 = 4*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  
  7.         sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  
  8.         sgbm.minDisparity = 0;  
  9.         sgbm.numberOfDisparities = 32;  
  10.         sgbm.uniquenessRatio = 10;  
  11.         sgbm.speckleWindowSize = 100;  
  12.         sgbm.speckleRange = 32;  
  13.         sgbm.disp12MaxDiff = 1;  
  14.         sgbm(left , right , left_disp_);  
  15.         sgbm(right, left  , right_disp_);  

各引數設定如BM方法,速度比較快,320*240的灰度圖匹配時間為78ms,視差效果如下圖。

第三種為GC方法:

  1. CvStereoGCState* state = cvCreateStereoGCState( 16, 2 );  
  2.  left_disp_  =cvCreateMat( left->height,left->width, CV_32F );  
  3.  right_disp_ =cvCreateMat( right->height,right->width,CV_32F );  
  4.  cvFindStereoCorrespondenceGC( left, right, left_disp_, right_disp_, state, 0 );  
  5.  cvReleaseStereoGCState( &state );  

該方法速度超慢,但效果超好。

各方法理論可以參考文獻

BM、GC、SGBM三種演算法的比較和BM在OpenCV3下的引數設定

第一部分BM、GC和SGBM演算法的效能比較轉自:http://blog.csdn.net/chenyusiyuan/article/details/5967291,其中原博主推薦的Stefano Mattoccia大神的講義Stereo Vision:algorithms and applications,我看了以後覺得非常受用,講的非常條理全面,裡面的參考文獻也很經典。第二部分為原創,主要是在OpenCV3.2版本下BM演算法的用法改變和引數說明。

    1.BM、GC和SGBM演算法效能比較:

    (1)視差效果:BM<SGBM<GC;

    (2)處理速度:BM>SGBM>GC;

    (3)影象型別:BM和GC演算法只能對8位灰度影象計算視差,SGBM演算法可以處理24位彩色影象;

(4) SGBM 立體匹配演算法(源自Heiko Hirschmuller的《Stereo Processing by Semi-global Matching and Mutual Information》),可以獲得比 BM 演算法物體輪廓更清晰的視差圖(但低紋理區域容易出現橫/斜紋路,在 GCstate->fullDP 選項使能時可消減這種異常紋路,但對應區域視差變為0,且執行速度會有所下降),速度比 BM 稍慢, 352*288的幀處理速度大約是 5 幀/秒;

    2.OpenCV3中BM演算法的使用更新:

    在OpenCV3中,StereoBM演算法發生了比較大的變化,StereoBM被定義為純虛類,因此不能直接例項化,只能用智慧指標的形式例項化,也不用StereoBMState類來設定了,而是改成用bm->set...的形式,詳細看如下程式碼。

  1. //BM(bidirectional matching)演算法進行雙向匹配,首先通過匹配代價在右圖中計算得出匹配點。  
  2. //然後相同的原理及計算在左圖中的匹配點。比較找到的左匹配點和源匹配點是否一致,如果是,則匹配成功。  
  3. //初始化 stereoBMstate 結構體  
  4. //錯誤:不允許使用抽象型別的stereoBM物件  
  5. //C++中含有純虛擬函式並且所有純虛擬函式並未完全實現的類稱為抽象類,它不能生成物件  
  6. //opencv3以後的版本不能這麼用了  
  7. //StereoBM bm;  
  8. //int unitDisparity = 15;//40  
  9. //int numberOfDisparities = unitDisparity * 16;  
  10. //bm.state->roi1 = roi1;  
  11. //bm.state->roi2 = roi2;  
  12. //bm.state->preFilterCap = 13;  
  13. //bm.state->SADWindowSize = 19;                                       
  14. //bm.state->minDisparity = 0;                                        
  15. //bm.state->numberOfDisparities = numberOfDisparities;               
  16. //bm.state->textureThreshold = 1000;                                
  17. //bm.state->uniquenessRatio = 1;                                   
  18. //bm.state->speckleWindowSize = 200;                              
  19. //bm.state->speckleRange = 32;                             
  20. //bm.state->disp12MaxDiff = -1;  
  21. cv::Ptr<cv::StereoBM>bm = cv::StereoBM::create();  
  22. int unitDisparity = 15;//40  
  23. int numberOfDisparities = unitDisparity * 16;  
  24. bm->setROI1(roi1);  
  25. bm->setROI2 (roi2);  
  26. bm->setPreFilterCap(13);  
  27. bm->setBlockSize = 15;                          //SAD視窗大小  
  28. bm->setMinDisparity(0);                         //確定匹配搜尋從哪裡開始  預設值是0  
  29. bm->setNumDisparities(numberOfDisparities) ;    //在該數值確定的視差範圍內進行搜尋,視差視窗  
  30.                                                 //  即最大視差值與最小視差值之差, 大小必須是16的整數倍  
  31. bm->setTextureThreshold(1000);                  //保證有足夠的紋理以克服噪聲  
  32. bm->setUniquenessRatio(1);                      //使用匹配功能模式  
  33. bm->setSpeckleWindowSize(200);                  //檢查視差連通區域變化度的視窗大小, 值為0時取消 speckle 檢查  
  34. bm->setSpeckleRange(32);                        // 視差變化閾值,當視窗內視差變化大於閾值時,該視窗內的視差清零  
  35. bm->setDisp12MaxDiff(-1);                       //左視差圖(直接計算得出)和右視差圖(通過cvValidateDisparity計算得出)  
  36.                                                 //  之間的最大容許差異,預設為-1  

      最後需要注意的是,在上述引數中,對視差生成效果影響較大的主要引數是setSADWindowSize、setNumberDisparities和setUniquenessRatio,這三個引數要重點關注和調整。其他引數的影響不算很大。

http://www.cnblogs.com/xrwang/archive/2010/04/29/stereosgbmandsetwindowproperty.html

模擬人的兩隻眼睛的Stereo相機最近變得很受歡迎。通過對stereo相機拍攝的左右兩張圖進行匹配找出視差圖,可以還原物體的3D資訊。立體匹配(Stereo matching)的步驟如下:

1: 預處理:亮度歸一化,去噪,影象增強,濾波等等 2: 匹配Cost計算Cost aggregation       每個畫素點的matching cost可用下圖所示的兩種方式表示      立體匹配演算法(Stereo <wbr>Matching)及其在OpenCV中的應用    將所有畫素的Cost加起來,選擇和最小的方案。 3: 全域性最優化 4: 後處理:Refinement 精化 一般基於畫素點的匹配含有較大的噪音,所以人們更願意使用基於區域性或全域性的匹配演算法。常用的立體匹配演算法可分為基於區域性的匹配方法和基於全域性的匹配方法。 (1)基於區域性的匹配演算法:塊匹配,模板匹配,SIFT[1],SURF[2],AKAZE[3] (2)基於全域性的匹配演算法:首先定義Cost Function,然後根據約束條件優化Cost Function.
  •       Dynamic Programming
  •            Scaling Optimization
  •            Graph Cuts
  •            Belief Propagation:Markov Random Field
           一般的Cost Function如下:ED基於畫素的亮度,Es基於畫素鄰居之間的Smoothness。                     立體匹配演算法(Stereo <wbr>Matching)及其在OpenCV中的應用
       在這裡簡單介紹後兩種全域性匹配演算法:        1:Graph Cut: 將每一個畫素看作Graph中的一個Node,然後假設該圖有L個不同的深度值,則新增L個            新的Node作為Label,然後求視差圖的問題就變成了多重Labelling的問題了,具體Graph Cut參照文            獻[4]。    2:Belief Propagation: 將影象看作馬爾科夫隨機場,則求視差問題變成了最大化聯合後驗概率的問題,              每一個畫素對其深度值的猜測來自於其鄰居給的資訊,然後再把資訊傳給其他的鄰居。每一個資訊有                    一個可靠度(概率)。最後經過多次迴圈深度值會收斂。   [2]Herbert Bay,Tinne Tuytelaars, and Luc Van Gool,SURF: Speeded Up Robust Features,ECCV,2006   [4]Yuri Boykov and Vladimir Kolmogorov (2003), "Computing Geodesics and Minimal Surfaces via Graph Cuts"   OpenCV提供了以下四種立體匹配演算法的函式:
  1.      Block Matching(BM) StereoBM
  2.      Semi-Global Block Matching(SGBM) StereoSGBM
  3.      Graph Cut(GC)cvStereoGCState()
  4.      Dynamic Programming(DP)cvFindStereoCorrespondence()
  第一種就是簡單的塊匹配,第三,四種是基於全域性的匹配,以下簡單介紹一下第二種演算法。我們知道區域性匹配   計算量小速度快,而全域性匹配計算量大速度慢,所以作者提出了SGBM演算法[5]:      第一步對每一個Pixel使用塊匹配BM進行匹配,得到了全部Pixel的disparity map。      第二步對Disparity map建立圖,用Graph Cut對其進行全域性優化。利用Rectification將二維轉化為一維:        則對每一個畫素的可能的Disparity值d,從以下4中裡面選取一個最小值:
  • 左相鄰畫素disparity取值為d時,其最小的cost值。
  • 左相鄰畫素disparity取值為d-1時,其最小的cost值+懲罰1。
  • 左相鄰畫素disparity取值為d+1時,其最小的cost值+懲罰1。
  • 左相鄰畫素disparity取值為其他時,其最小的cost值+懲罰2。
        它與GC的區別在於它的左相鄰畫素的Disparity是已知的(根據塊匹配結果),而GC是未知的,所以GC   要對每一種取值進行一次計算,計算量比SGBM要大得多。   [5]H. Hirschmuller, Stereo Processing by Semi-global Matching and Mutual Information,"IEEE Transactions on Pattern Analysis and Machine          Intelligence, Vol. 30, Issue 2, pp. 328-341, Feb. 2008.      下圖給出了各種不同演算法的結果比較:      左右原圖如下:      立體匹配演算法(Stereo <wbr>Matching)及其在OpenCV中的應用
    匹配結果如下:
立體匹配演算法(Stereo <wbr>Matching)及其在OpenCV中的應用      精度與速度統計圖如下:                                   立體匹配演算法(Stereo <wbr>Matching)及其在OpenCV中的應用