双目立体视觉匹配算法-----SAD匹配算法、BM算法、SGBM算法、GC算法 2016年11月23日 11:11:54 阅读数:19959 一、 SAD算法 1.算法原理 SAD(

转载自:https://blog.csdn.net/liulina603/article/details/53302168

一、 SAD算法

1.算法原理
        SAD(Sum of absolute differences)是一种图像匹配算法。基本思想:差的绝对值之和。此算法常用于图像块匹配,将每个像素对应数值之差的绝对值求和,据此评估两个图像块的相似度该算法快速、但并不精确通常用于多级处理的初步筛选。
2.基本流程

输入:两幅图像,一幅Left-Image,一幅Right-Image

对左图,依次扫描,选定一个锚点:

(1)构造一个小窗口,类似于卷积核;
(2)用窗口覆盖左边的图像,选择出窗口覆盖区域内的所有像素点;
(3)同样用窗口覆盖右边的图像并选择出覆盖区域的像素点;
(4)左边覆盖区域减去右边覆盖区域,并求出所有像素点灰度差的绝对值之和;
(5)移动右边图像的窗口,重复(3)-(4)的处理(这里有个搜索范围,超过这个范围跳出);
(6)找到这个范围内SAD值最小的窗口,即找到了左图锚点的最佳匹配的像素块。


参考代码:SAD.h

[cpp]  view plain  copy
  1. #include"iostream"  
  2. #include"opencv2/opencv.hpp"  
  3. #include"iomanip"  
  4. using namespace std;  
  5. using namespace cv;  
  6.   
  7. class SAD  
  8. {  
  9.     public:  
  10.         SAD():winSize(7),DSR(30){}  
  11.         SAD(int _winSize,int _DSR):winSize(_winSize),DSR(_DSR){}  
  12.         Mat computerSAD(Mat &L,Mat &R); //计算SAD  
  13.     private:  
  14.         int winSize; //卷积核的尺寸  
  15.         int DSR;     //视差搜索范围  
  16.       
  17. };  
  18.   
  19.  Mat SAD::computerSAD(Mat &L,Mat &R)  
  20.     {  
  21.         int Height=L.rows;  
  22.         int Width=L.cols;  
  23.         Mat Kernel_L(Size(winSize,winSize),CV_8U,Scalar::all(0));  
  24.         Mat Kernel_R(Size(winSize,winSize),CV_8U,Scalar::all(0));  
  25.         Mat Disparity(Height,Width,CV_8U,Scalar(0)); //视差图  
  26.   
  27.         for(int i=0;i<Width-winSize;i++)  //左图从DSR开始遍历  
  28.         {  
  29.             for(int j=0;j<Height-winSize;j++)  
  30.             {  
  31.                 Kernel_L=L(Rect(i,j,winSize,winSize));  
  32.                 Mat MM(1,DSR,CV_32F,Scalar(0)); //  
  33.   
  34.                 for(int k=0;k<DSR;k++)  
  35.                 {  
  36.                     int x=i-k;  
  37.                     if(x>=0)  
  38.                     {  
  39.                     Kernel_R=R(Rect(x,j,winSize,winSize));  
  40.                     Mat Dif;  
  41.                     absdiff(Kernel_L, Kernel_R, Dif);//  
  42.                     Scalar ADD=sum(Dif);  
  43.                     float a=ADD[0];  
  44.                     MM.at<float>(k)=a;  
  45.                     }  
  46.                       
  47.                 }  
  48.                 Point minLoc;  
  49.                 minMaxLoc(MM, NULL, NULL,&minLoc,NULL);  
  50.                   
  51.                 int loc=minLoc.x;  
  52.                 //int loc=DSR-loc;  
  53.                 Disparity.at<char>(j,i)=loc*16;  
  54.                   
  55.             }  
  56.             double rate=double(i)/(Width);  
  57.             cout<<"已完成"<<setprecision(2)<<rate*100<<"%"<<endl; //处理进度  
  58.         }  
  59.         return Disparity;  
  60.     }  
[cpp]  view plain  copy
  1. // MySAD.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3. #include "stdafx.h"  
  4. #include"SAD.h"  
  5. int _tmain(int argc, _TCHAR* argv[])  
  6. {  
  7.     Mat Img_L=imread("imL.png",0);  
  8.     Mat Img_R=imread("imR.png",0);  
  9.     Mat Disparity;    //视差图  
  10.       
  11.     //SAD mySAD;  
  12.     SAD mySAD(7,30);  
  13.     Disparity=mySAD.computerSAD(Img_L,Img_R);  
  14.   
  15.     imshow("Img_L",Img_L);  
  16.     imshow("Img_R",Img_R);  
  17.     imshow("Disparity",Disparity);  
  18.     waitKey();  
  19.     return 0;  
  20. }  
[cpp]  view plain  copy
  1.   

扫描二维码关注公众号,回复: 1660895 查看本文章

二、BM算法:速度很快,效果一般

SGBM算法 Stereo Processing by Semiglobal Matching and Mutual Information

GC算法 算法文献:Realistic CG Stereo Image Dataset with Ground Truth Disparity Maps

参考:http://blog.csdn.net/wqvbjhc/article/details/6260844

[cpp]  view plain  copy
  1. void BM()  
  2. {  
  3.   IplImage * img1 = cvLoadImage("left.png",0);  
  4.     IplImage * img2 = cvLoadImage("right.png",0);  
  5.     CvStereoBMState* BMState=cvCreateStereoBMState();  
  6.     assert(BMState);  
  7.     BMState->preFilterSize=9;  
  8.     BMState->preFilterCap=31;  
  9.     BMState->SADWindowSize=15;  
  10.     BMState->minDisparity=0;  
  11.     BMState->numberOfDisparities=64;  
  12.     BMState->textureThreshold=10;  
  13.     BMState->uniquenessRatio=15;  
  14.     BMState->speckleWindowSize=100;  
  15.     BMState->speckleRange=32;  
  16.     BMState->disp12MaxDiff=1;  
  17.   
  18.     CvMat* disp=cvCreateMat(img1->height,img1->width,CV_16S);  
  19.     CvMat* vdisp=cvCreateMat(img1->height,img1->width,CV_8U);  
  20.     int64 t=getTickCount();  
  21.     cvFindStereoCorrespondenceBM(img1,img2,disp,BMState);  
  22.     t=getTickCount()-t;  
  23.     cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;  
  24.     cvSave("disp.xml",disp);  
  25.     cvNormalize(disp,vdisp,0,255,CV_MINMAX);  
  26.     cvNamedWindow("BM_disparity",0);  
  27.     cvShowImage("BM_disparity",vdisp);  
  28.     cvWaitKey(0);  
  29.     //cvSaveImage("cones\\BM_disparity.png",vdisp);  
  30.     cvReleaseMat(&disp);  
  31.     cvReleaseMat(&vdisp);  
  32.     cvDestroyWindow("BM_disparity");  
  33. }  


三、SGBM算法

作为一种全局匹配算法,立体匹配的效果明显好于局部匹配算法,但是同时复杂度上也要远远大于局部匹配算法。算法主要是参考Stereo Processing by Semiglobal Matching and Mutual Information。

opencv中实现的SGBM算法计算匹配代价没有按照原始论文的互信息作为代价,而是按照块匹配的代价。

参考:http://www.opencv.org.cn/forum.php?mod=viewthread&tid=23854

[cpp]  view plain  copy
  1. #include <highgui.h>  
  2. #include <cv.h>  
  3. #include <cxcore.h>  
  4. #include <iostream>  
  5. using namespace std;  
  6. using namespace cv;  
  7. int main()  
  8. {  
  9.   
  10.     IplImage * img1 = cvLoadImage("left.png",0);  
  11.     IplImage * img2 = cvLoadImage("right.png",0);  
  12.     cv::StereoSGBM sgbm;  
  13.     int SADWindowSize = 9;  
  14.     sgbm.preFilterCap = 63;  
  15.     sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3;  
  16.     int cn = img1->nChannels;  
  17.     int numberOfDisparities=64;  
  18.     sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  
  19.     sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;  
  20.     sgbm.minDisparity = 0;  
  21.     sgbm.numberOfDisparities = numberOfDisparities;  
  22.     sgbm.uniquenessRatio = 10;  
  23.     sgbm.speckleWindowSize = 100;  
  24.     sgbm.speckleRange = 32;  
  25.     sgbm.disp12MaxDiff = 1;  
  26.     Mat disp, disp8;  
  27.     int64 t = getTickCount();  
  28.     sgbm((Mat)img1, (Mat)img2, disp);  
  29.     t = getTickCount() - t;  
  30.     cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;  
  31.     disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));  
  32.   
  33.     namedWindow("left", 1);  
  34.     cvShowImage("left", img1);  
  35.     namedWindow("right", 1);  
  36.     cvShowImage("right", img2);  
  37.     namedWindow("disparity", 1);  
  38.     imshow("disparity", disp8);  
  39.     waitKey();  
  40.     imwrite("sgbm_disparity.png", disp8);     
  41.     cvDestroyAllWindows();  
  42.     return 0;  
  43. }  


四、GC算法 效果最好,速度最慢


[cpp]  view plain  copy
  1. void GC()  
  2. {  
  3.     IplImage * img1 = cvLoadImage("left.png",0);  
  4.     IplImage * img2 = cvLoadImage("right.png",0);  
  5.     CvStereoGCState* GCState=cvCreateStereoGCState(64,3);  
  6.     assert(GCState);  
  7.     cout<<"start matching using GC"<<endl;  
  8.     CvMat* gcdispleft=cvCreateMat(img1->height,img1->width,CV_16S);  
  9.     CvMat* gcdispright=cvCreateMat(img2->height,img2->width,CV_16S);  
  10.     CvMat* gcvdisp=cvCreateMat(img1->height,img1->width,CV_8U);  
  11.     int64 t=getTickCount();  
  12.     cvFindStereoCorrespondenceGC(img1,img2,gcdispleft,gcdispright,GCState);  
  13.     t=getTickCount()-t;  
  14.     cout<<"Time elapsed:"<<t*1000/getTickFrequency()<<endl;  
  15.     //cvNormalize(gcdispleft,gcvdisp,0,255,CV_MINMAX);  
  16.     //cvSaveImage("GC_left_disparity.png",gcvdisp);  
  17.     cvNormalize(gcdispright,gcvdisp,0,255,CV_MINMAX);  
  18.     cvSaveImage("GC_right_disparity.png",gcvdisp);  
  19.   
  20.   
  21.     cvNamedWindow("GC_disparity",0);  
  22.     cvShowImage("GC_disparity",gcvdisp);  
  23.     cvWaitKey(0);  
  24.     cvReleaseMat(&gcdispleft);  
  25.     cvReleaseMat(&gcdispright);  
  26.     cvReleaseMat(&gcvdisp);  
  27. }  


猜你喜欢

转载自blog.csdn.net/cyem1/article/details/80736658