基於Opencv的幾種立體匹配算法+ELAS

http://blog.csdn.net/chuhang_zhqr/article/details/51179881類似,採用
這裏寫圖片描述

這裏寫圖片描述
這兩個經典的圖片進行測試。

關於BM和SGBM以及VAR的參數設置請參考
晨宇思遠

本文代碼基於opencv2.4.9
本文源碼地址在我的CSDN代碼資源:
http://download.csdn.net/detail/chuhang_zhqr/9703763

0:ELAS
這裏要去下載Elas的開源庫函數。

int StereoMatch::ElasMatch()
{
    cv::Mat disp_l,disp_r,disp8u_l,disp8u_r;
    double minVal; double maxVal; //視差圖的極值

    cv::Mat leftImage = cv::imread("../test_images/leftr31.png",0);
    cv::Mat rightImage = cv::imread("../test_images/rightr31.png",0);

    // 計算視差
    // generate disparity image using LIBELAS
    int bd = 0;
    const int32_t dims[3] = {leftImage.cols,leftImage.rows,leftImage.cols};
    cv::Mat leftdpf = cv::Mat::zeros(cv::Size(leftImage.cols,leftImage.rows), CV_32F);
    cv::Mat rightdpf = cv::Mat::zeros(cv::Size(leftImage.cols,leftImage.rows), CV_32F);
    Elas::parameters param;
    param.postprocess_only_left = false;
    Elas elas(param);
    elas.process(leftImage.data,rightImage.data,leftdpf.ptr<float>(0),rightdpf.ptr<float>(0),dims);

    cv::Mat(leftdpf(cv::Rect(bd,0,leftImage.cols,leftImage.rows))).copyTo(disp_l);
    cv::Mat(rightdpf(cv::Rect(bd,0,rightImage.cols,rightImage.rows))).copyTo(disp_r);

    //-- Check its extreme values
    cv::minMaxLoc( disp_l, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- Display it as a CV_8UC1 image
    disp_l.convertTo(disp8u_l, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)

    cv::minMaxLoc( disp_r, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- Display it as a CV_8UC1 image
    disp_r.convertTo(disp8u_r, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)

    cv::normalize(disp8u_l, disp8u_l, 0, 255, CV_MINMAX, CV_8UC1);    // obtain normalized image
    cv::normalize(disp8u_r, disp8u_r, 0, 255, CV_MINMAX, CV_8UC1);    // obtain normalized image

    cv::imshow("Left",leftImage);
    cv::imshow("Right",rightImage);

    cv::imshow("Elas_left",disp8u_l);
    cv::imshow("Elas_right",disp8u_r);
    cv::imwrite("Elas_left.png",disp8u_l);
    cv::imwrite("Elas_right.png",disp8u_r);

    cout<<endl<<"Over"<<endl;
    cv::waitKey(0);

    return 0;
}

1:BM算法

int StereoMatch::BMMatching()
{
    cv::Mat disp,disp8u;
    double minVal; double maxVal; //視差圖的極值

    cv::Mat leftImage = cv::imread("../test_images/leftr.png",0);
    cv::Mat rightImage = cv::imread("../test_images/rightr.png",0);

    int SADWindowSize = 19;
    int numberOfDisparities =16*3; /**< Range of disparity */
    numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((leftImage.cols/8) + 15) & -16;

    //bm.state->roi1 = remapMat.Calib_Roi_L;//左右視圖的有效像素區域,一般由雙目校正階段的 cvStereoRectify 函數傳遞,也可以自行設定。
    //bm.state->roi2 = remapMat.Calib_Roi_R;//一旦在狀態參數中設定了 roi1 和 roi2,OpenCV 會通過cvGetValidDisparityROI 函數計算出視差圖的有效區域,在有效區域外的視差值將被清零。
    //bm.State->preFilterSize=41;//預處理濾波器窗口大小,5-21,odd
    bm.state->preFilterCap = 31; //63,1-31//預處理濾波器的截斷值,預處理的輸出值僅保留[-preFilterCap, preFilterCap]範圍內的值,
    bm.state->SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 9; //SAD窗口大小5-21
    bm.state->minDisparity = 0; //64 最小視差,默認值爲 0
    bm.state->numberOfDisparities = numberOfDisparities; //128視差窗口,即最大視差值與最小視差值之差, 窗口大小必須是 16 的整數倍
    bm.state->textureThreshold = 10;//低紋理區域的判斷閾值。如果當前SAD窗口內所有鄰居像素點的x導數絕對值之和小於指定閾值,則該窗口對應的像素點的視差值爲 0
    bm.state->uniquenessRatio = 15;//5-15 視差唯一性百分比, 視差窗口範圍內最低代價是次低代價的(1 + uniquenessRatio/100)倍時,最低代價對應的視差值纔是該像素點的視差,否則該像素點的視差爲 0
    bm.state->speckleWindowSize = 100;//檢查視差連通區域變化度的窗口大小, 值爲 0 時取消 speckle 檢查
    bm.state->speckleRange = 32;//視差變化閾值,當窗口內視差變化大於閾值時,該窗口內的視差清零
    bm.state->disp12MaxDiff = 1;//左視差圖(直接計算得出)和右視差圖(通過cvValidateDisparity計算得出)之間的最大容許差異。超過該閾值的視差值將被清零。該參數默認爲 -1,即不執行左右視差檢查。
                                                      //注意在程序調試階段最好保持該值爲 -1,以便查看不同視差窗口生成的視差效果。

    // 計算視差
    bm(leftImage, rightImage, disp);

    //-- Check its extreme values
    cv::minMaxLoc( disp, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- 4. Display it as a CV_8UC1 image
    disp.convertTo(disp8u, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)
    cv::normalize(disp8u, disp8u, 0, 255, CV_MINMAX, CV_8UC1);    // obtain normalized image

    cv::imshow("left",leftImage);
    cv::imshow("right",leftImage);
    cv::imshow("Disp",disp8u);
    cv::imwrite("bm.png",disp8u);
    cv::waitKey(0);

}

這裏寫圖片描述

2:SGBM

int StereoMatch::SGBMMatching()
{
    cv::Mat disp,disp8u;
    double minVal; double maxVal; //視差圖的極值

    cv::Mat leftImage = cv::imread("../test_images/leftr.png",0);
    cv::Mat rightImage = cv::imread("../test_images/rightr.png",0);

    int numberOfDisparities =16*2; /**< Range of disparity */
    numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((leftImage.cols/8) + 15) & -16;

    int SADWindowSize = 11;
    sgbm.preFilterCap = 63;
    sgbm.SADWindowSize = SADWindowSize > 0 ? SADWindowSize : 3; //3-11

    int cn = leftImage.channels();

    sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;//P1、P2的值越大,視差越平滑。P2>P1,可取(50,800)或者(40,2500)
    sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowSize;
    sgbm.minDisparity = 0;
    sgbm.numberOfDisparities = numberOfDisparities; //128,256
    sgbm.uniquenessRatio = 10;    //10,0
    sgbm.speckleWindowSize = 100; //200
    sgbm.speckleRange = 32;
    sgbm.disp12MaxDiff = 1;
    sgbm.fullDP = 1;

    // 計算視差
    sgbm(leftImage, rightImage, disp);

    //-- Check its extreme values
    cv::minMaxLoc( disp, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- 4. Display it as a CV_8UC1 image
    disp.convertTo(disp8u, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)
    cv::normalize(disp8u, disp8u, 0, 255, CV_MINMAX, CV_8UC1);    // obtain normalized image

    cv::imshow("left",leftImage);
    cv::imshow("right",leftImage);
    cv::imshow("Disp",disp8u);
    cv::imwrite("sgbm.png",disp8u);
    cv::waitKey(0);

}

這裏寫圖片描述

3:VAR

int StereoMatch::VARMatching()
{
    cv::Mat disp,disp8u;
    double minVal; double maxVal; //視差圖的極值

    cv::Mat leftImage = cv::imread("../test_images/leftr.png",0);
    cv::Mat rightImage = cv::imread("../test_images/rightr.png",0);

    int numberOfDisparities =16*2; /**< Range of disparity */
    numberOfDisparities = numberOfDisparities > 0 ? numberOfDisparities : ((leftImage.cols/8) + 15) & -16;

    var.levels = 3;                                 // ignored with USE_AUTO_PARAMS
    var.pyrScale = 0.5;                             // ignored with USE_AUTO_PARAMS
    var.nIt = 25;
    var.minDisp = -numberOfDisparities;
    var.maxDisp = 0;
    var.poly_n = 3;
    var.poly_sigma = 0.0;
    var.fi = 15.0f;
    var.lambda = 0.03f;
    var.penalization = var.PENALIZATION_TICHONOV;   // ignored with USE_AUTO_PARAMS
    var.cycle = var.CYCLE_V;                        // ignored with USE_AUTO_PARAMS
    var.flags = var.USE_SMART_ID | var.USE_AUTO_PARAMS | var.USE_INITIAL_DISPARITY | var.USE_MEDIAN_FILTERING ;

    // 計算視差
    var(leftImage, rightImage, disp);

    //-- Check its extreme values
    cv::minMaxLoc( disp, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<endl<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- 4. Display it as a CV_8UC1 image
    disp.convertTo(disp8u, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)
    cv::normalize(disp8u, disp8u, 0, 255, CV_MINMAX, CV_8UC1);    // obtain normalized image

    cv::imshow("left",leftImage);
    cv::imshow("right",leftImage);
    cv::imshow("Disp",disp8u);
    cv::imwrite("var.png",disp8u);
    cv::waitKey(0);

}

4:GC
GC好像只有在c版本的,我這裏做了兩個,一個是C的,一個是改了接口的C++版本的。

int StereoMatch::GCMatching()
{
    IplImage * leftImage = cvLoadImage("../test_images/leftr31.png",0);
    IplImage * rightImage = cvLoadImage("../test_images/rightr31.png",0);

    CvStereoGCState* state = cvCreateStereoGCState( 16, 4 );
    IplImage * left_disp_  =cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
    IplImage * right_disp_ =cvCreateImage(cvGetSize(leftImage),leftImage->depth,1);
    cvFindStereoCorrespondenceGC( leftImage, rightImage, left_disp_, right_disp_, state, 0 );
    cvReleaseStereoGCState( &state );

    cvNamedWindow("Left",1);
    cvNamedWindow("Right",1);
    cvNamedWindow("GC_left",1);
    cvNamedWindow("GC_right",1);

    cvShowImage("Left",leftImage);
    cvShowImage("Right",rightImage);

    cvNormalize(left_disp_,left_disp_,0,255,CV_MINMAX,CV_8UC1);
    cvNormalize(right_disp_,right_disp_,0,255,CV_MINMAX,CV_8UC1);

    cvShowImage("GC_left",left_disp_);
    cvShowImage("GC_right",right_disp_);
    cvSaveImage("GC_left.png",left_disp_);
    cvSaveImage("GC_right.png",right_disp_);


    cout<<endl<<"Over"<<endl;
    cvWaitKey(0);
    cvDestroyAllWindows();
    cvReleaseImage(&leftImage);
    cvReleaseImage(&rightImage);
    return 0;
}
int StereoMatch::GCMatching_Mat()
{
    double minVal; double maxVal; //視差圖的極值
    cv::Mat disp8u_l,disp8u_r;

    cv::Mat leftImage = cv::imread("../test_images/leftr31.png",0);
    cv::Mat rightImage = cv::imread("../test_images/rightr31.png",0);

    CvStereoGCState* state = cvCreateStereoGCState( 16, 5 );
    cv::Mat left_disp_  =leftImage.clone();
    cv::Mat right_disp_ =rightImage.clone();

    IplImage temp = (IplImage)leftImage;
    IplImage* leftimg = &temp;
    IplImage temp1 = (IplImage)rightImage;
    IplImage* rightimg = &temp1;
    IplImage temp2 = (IplImage)left_disp_;
    IplImage* leftdisp = &temp2;
    IplImage temp3 = (IplImage)right_disp_;
    IplImage* rightdisp = &temp3;

    cvFindStereoCorrespondenceGC( leftimg, rightimg, leftdisp, rightdisp, state, 0 );
    cvReleaseStereoGCState( &state );

    cv::namedWindow("Left",1);
    cv::namedWindow("Right",1);
    cv::namedWindow("GC_left",1);
    cv::namedWindow("GC_right",1);

    cv::imshow("Left",leftImage);
    cv::imshow("Right",rightImage);

/*    //-- Check its extreme values
    cv::minMaxLoc(right_disp_, &minVal, &maxVal );
    cout<<"Min disp: Max value"<< minVal<<maxVal; //numberOfDisparities.= (maxVal - minVal)

    //-- Display it as a CV_8UC1 image
    right_disp_.convertTo(disp8u_r, CV_8U, 255/(maxVal - minVal));//(numberOfDisparities*16.)

    cv::normalize(left_disp_,left_disp_,0,255,CV_MINMAX,CV_8UC1);
    cv::normalize(disp8u_r,disp8u_r,0,255,CV_MINMAX,CV_8UC1);
*/
    cv::normalize(left_disp_,left_disp_,0,255,CV_MINMAX,CV_8UC1);
    cv::normalize(right_disp_,right_disp_,0,255,CV_MINMAX,CV_8UC1);

    cv::imshow("GC_left",left_disp_);
    cv::imshow("GC_right",right_disp_);
    cv::imwrite("GC_left.png",left_disp_);
    cv::imwrite("GC_right.png",right_disp_);

    cout<<endl<<"Over"<<endl;
    cv::waitKey(0);

    return 0;
}

這裏寫圖片描述

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