您的位置:首页 > 其它

【视觉-立体视觉】立体匹配几种算法性能比较

2018-02-03 21:11 2779 查看

OpenCV三种立体匹配求视差图算法总结

http://blog.csdn.net/mailang2008/article/details/5873883

对OpenCV中涉及的三种立体匹配算法进行代码及各自优缺点总结:

首先我们看一下BM算法:

该算法代码:

[cpp] view
plain copy

CvStereoBMState *BMState = cvCreateStereoBMState();  

  

int SADWindowSize=15;   

 BMState->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9;  

 BMState->minDisparity = 0;  

 BMState->numberOfDisparities = 32;  

 BMState->textureThreshold = 10;  

 BMState->uniquenessRatio = 15;  

 BMState->speckleWindowSize = 100;  

 BMState->speckleRange = 32;  

 BMState->disp12MaxDiff = 1;  

 cvFindStereoCorrespondenceBM( left, right, left_disp_,BMState);  

   cvNormalize( left_disp_, left_vdisp, 0, 256, CV_MINMAX );  

其中minDisparity是控制匹配搜索的第一个参数,代表了匹配搜苏从哪里开始,numberOfDisparities表示最大搜索视差数uniquenessRatio表示匹配功能函数,这三个参数比较重要,可以根据实验给予参数值。

该方法速度最快,一副320*240的灰度图匹配时间为31ms,视差图如下。

 



第二种方法是SGBM方法这是OpenCV的一种新算法:

[cpp] view
plain copy

cv::StereoSGBM sgbm;  

        sgbm.preFilterCap = 63;  

        int SADWindowSize=11;   

        int cn = 1;  

        sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;  

        sgbm.P1 = 4*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  

        sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  

        sgbm.minDisparity = 0;  

        sgbm.numberOfDisparities = 32;  

        sgbm.uniquenessRatio = 10;  

        sgbm.speckleWindowSize = 100;  

        sgbm.speckleRange = 32;  

        sgbm.disp12MaxDiff = 1;  

      

        sgbm(left , right , left_disp_);  

        sgbm(right, left  , right_disp_);  

 

各参数设置如BM方法,速度比较快,320*240的灰度图匹配时间为78ms,视差效果如下图。

 

 



第三种为GC方法:

[cpp] view
plain copy

CvStereoGCState* state = cvCreateStereoGCState( 16, 2 );  

 left_disp_  =cvCreateMat( left->height,left->width, CV_32F );  

 right_disp_ =cvCreateMat( right->height,right->width,CV_32F );  

 cvFindStereoCorrespondenceGC( left, right, left_disp_, right_disp_, state, 0 );  

 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...的形式,详细看如下代码。

[html] view
plain copy

//BM(bidirectional matching)算法进行双向匹配,首先通过匹配代价在右图中计算得出匹配点。  

//然后相同的原理及计算在左图中的匹配点。比较找到的左匹配点和源匹配点是否一致,如果是,则匹配成功。  

//初始化 stereoBMstate 结构体  

//错误:不允许使用抽象类型的stereoBM对象  

//C++中含有纯虚拟函数并且所有纯虚函数并未完全实现的类称为抽象类,它不能生成对象  

//opencv3以后的版本不能这么用了  

//StereoBM bm;  

//int unitDisparity = 15;//40  

//int numberOfDisparities = unitDisparity * 16;  

//bm.state->roi1 = roi1;  

//bm.state->roi2 = roi2;  

//bm.state->preFilterCap = 13;  

//bm.state->SADWindowSize = 19;                                       

//bm.state->minDisparity = 0;                                        

//bm.state->numberOfDisparities = numberOfDisparities;               

//bm.state->textureThreshold = 1000;                                

//bm.state->uniquenessRatio = 1;                                   

//bm.state->speckleWindowSize = 200;                              

//bm.state->speckleRange = 32;                             

//bm.state->disp12MaxDiff = -1;  

  

cv::Ptr<cv::StereoBM> bm = cv::StereoBM::create();  

int unitDisparity = 15;//40  

int numberOfDisparities = unitDisparity * 16;  

bm->setROI1(roi1);  

bm->setROI2 (roi2);  

bm->setPreFilterCap(13);  

bm->setBlockSize = 15;                          //SAD窗口大小  

bm->setMinDisparity(0);                         //确定匹配搜索从哪里开始  默认值是0  

bm->setNumDisparities(numberOfDisparities) ;    //在该数值确定的视差范围内进行搜索,视差窗口  

                                                //  即最大视差值与最小视差值之差, 大小必须是16的整数倍  

bm->setTextureThreshold(1000);                  //保证有足够的纹理以克服噪声  

bm->setUniquenessRatio(1);                      //使用匹配功能模式  

bm->setSpeckleWindowSize(200);                  //检查视差连通区域变化度的窗口大小, 值为0时取消 speckle 检查  

bm->setSpeckleRange(32);                        // 视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零  

bm->setDisp12MaxDiff(-1);                       //左视差图(直接计算得出)和右视差图(通过cvValidateDisparity计算得出)  

                                                //  之间的最大容许差异,默认为-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可用下图所示的两种方式表示

     



   将所有像素的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。

                    



       在这里简单介绍后两种全局匹配算法:

       1:Graph Cut: 将每一个像素看作Graph中的一个Node,然后假设该图有L个不同的深度值,则添加L个

           新的Node作为Label,然后求视差图的问题就变成了多重Labelling的问题了,具体Graph Cut参照文

           献[4]。

        2:Belief Propagation: 将图像看作马尔科夫随机场,则求视差问题变成了最大化联合后验概率的问题,

             每一个像素对其深度值的猜测来自于其邻居给的信息,然后再把信息传给其他的邻居。每一个信息有                    一个可靠度(概率)。最后经过多次循环深度值会收敛。

  [1]Lowe, David G. (2004). "Distinctive
Image Features from Scale-Invariant Keypoints"

  [2]Herbert Bay,Tinne Tuytelaars, and Luc Van Gool,SURF: Speeded Up Robust Features,ECCV,2006

  [3]Pablo F. Alcantarilla, Adrien
Bartoli and Andrew J. Davison, KAZE
Features. In European Conference on Computer Vision (ECCV),
2012.

  [4]Yuri Boykov and Vladimir Kolmogorov (2003),
"Computing Geodesics and Minimal Surfaces via Graph Cuts"

  OpenCV提供了以下四种立体匹配算法的函数:

     Block Matching(BM) StereoBM

     Semi-Global Block Matching(SGBM) StereoSGBM

     Graph Cut(GC)cvStereoGCState()

     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.

     下图给出了各种不同算法的结果比较:

     左右原图如下:

     



    匹配结果如下:

               



     精度与速度统计图如下:

                                  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: