立体匹配算法

转载请注明出处:http://www.cnblogs.com/adong7639/p/4267326.html

立体匹配算法最新动态:

http://vision.middlebury.edu/stereo/eval/

http://www.cvlibs.net/datasets/kitti/eval_stereo_flow.php?benchmark=stereo

相关文献:http://blog.csdn.net/xuyuhua1985/article/details/26283389

介绍立体匹配的基本原理: http://vision.deis.unibo.it/~smatt/Seminars/StereoVision.pdf(比较清晰)

立体匹配综述性文章 : http://wenku.baidu.com/view/5b359d7d5acfa1c7aa00cc7b.html

立体匹配算法的基本目标:找出图像的每个像素点在另一个视角的图像上对应的像素点,算出视差图像,估算出景深图像。

最简单的SAD块匹配算法

复制代码
//Stereo Match By SAD
#include <opencv2/opencv.hpp>
#include <vector>
#include <algorithm>
#include <iostream>  
#include <windows.h>  
#include <string>  

using namespace std;
using namespace cv;

DWORD t1;  
DWORD t2;  

void timebegin()  
{  
    t1 = GetTickCount();  
}  

void timeend(string str)  
{  
    t2 = GetTickCount();  
    cout << str << " is "<< (t2 - t1)/1000 << "s" << endl;  
}  


float sadvalue(const Mat &src1, const Mat &src2)
{
    Mat  matdiff = cv::abs(src1 -src2);
    int  saddiff = cv::sum(matdiff)[0];
    return saddiff;
}

float GetMinSadIndex(std::vector<float> &sad)
{
    float minsad = sad[0];
    int index = 0;
    int len = sad.size();
    for (int i = 1; i < len; ++i)
    {
        if (sad[i] < minsad)
        {
            minsad = sad[i];
            index = i;
        }
    }
    return index;
}

void MatDataNormal(const Mat &src, Mat &dst)
{
    normalize(src, dst, 255, 0, NORM_MINMAX );
    dst.convertTo(dst, CV_8UC1);
}


void GetPointDepthRight(Mat &disparity, const Mat &leftimg, const Mat  &rightimg, 
    const int MaxDisparity, const  int winsize)
{
    int row = leftimg.rows;
    int col = leftimg.cols;
    if (leftimg.channels() == 3 && rightimg.channels() == 3)
    {
        cvtColor(leftimg, leftimg, CV_BGR2GRAY);
        cvtColor(rightimg, rightimg, CV_BGR2GRAY);
    }

    //Mat disparity = Mat ::zeros(row,col, CV_32S);
    int w = winsize;
    int rowrange = row - w;
    int colrange = col - w - MaxDisparity;

    for (int i = w; i < rowrange; ++i)
    {
        int *ptr = disparity.ptr<int>(i);
        for (int j = w; j < colrange; ++j)
        {
            //Rect rightrect;
            Mat rightwin = rightimg(Range(i - w,i + w + 1),Range(j - w,j + w + 1)); 
            std::vector<float> sad(MaxDisparity);
            for (int d = j; d < j + MaxDisparity; ++d)
            {
                //Rect leftrect;
                Mat leftwin = leftimg(Range(i - w,i + w + 1),Range(d - w,d + w + 1));
                sad[d - j] = sadvalue(leftwin, rightwin);
            }
            *(ptr + j) = GetMinSadIndex(sad);
        }
    }
}

void GetPointDepthLeft(Mat &disparity, const  Mat &leftimg, const Mat  &rightimg, 
    const int MaxDisparity, const  int winsize)
{
    int row = leftimg.rows;
    int col = leftimg.cols;
    if (leftimg.channels() == 3 && rightimg.channels() == 3)
    {
        cvtColor(leftimg, leftimg, CV_BGR2GRAY);
        cvtColor(rightimg, rightimg, CV_BGR2GRAY);
    }

    //Mat disparity = Mat ::zeros(row,col, CV_32S);
    int w = winsize;
    int rowrange = row - w;
    int colrange = col - w;

    for (int i = w; i < rowrange; ++i)
    {
        int *ptr = disparity.ptr<int>(i);
        for (int j = MaxDisparity + w; j < colrange; ++j)
        {
            //Rect leftrect;
            Mat leftwin = leftimg(Range(i - w,i + w + 1),Range(j - w,j + w + 1)); 
            std::vector<float> sad(MaxDisparity);
            for (int d = j; d >  j -  MaxDisparity; --d)
            {
                //Rect rightrect;
                Mat rightwin = rightimg(Range(i - w,i + w + 1),Range(d - w,d + w + 1));
                sad[j - d] = sadvalue(leftwin, rightwin);
            }
            *(ptr + j) = GetMinSadIndex(sad);
        }
    }
}

//(Left-Right Consistency (LRC)
void CrossCheckDiaparity(const Mat &leftdisp, const Mat &rightdisp, Mat &lastdisp, 
    const int MaxDisparity, const int winsize)
{
    int row = leftdisp.rows;
    int col = rightdisp.cols;
    int w = winsize;
    int rowrange = row - w;
    int colrange = col - MaxDisparity - w;
    int diffthreshold = 2;
    for (int i = w; i < row -w; ++i)
    {
        const int *ptrleft = leftdisp.ptr<int>(i);
        const int *ptrright = rightdisp.ptr<int>(i);
        int *ptrdisp = lastdisp.ptr<int>(i);
        for (int j = MaxDisparity + w; j < col - MaxDisparity - w; ++j)
        {
            int leftvalue = *(ptrleft + j);
            int rightvalue = *(ptrright + j - leftvalue );
            int diff = abs(leftvalue - rightvalue);
            if (diff > diffthreshold)
            {
                *(ptrdisp + j) = 0;
            }else
            {
                *(ptrdisp + j) = leftvalue;
            }
        }
    }

}


int main()
{
    Mat leftimg = imread("left1.png",0);   
    Mat rightimg = imread("right1.png",0); 

    if (leftimg.channels() == 3 && rightimg.channels() == 3)
    {
        cvtColor(leftimg, leftimg, CV_BGR2GRAY);
        cvtColor(rightimg, rightimg, CV_BGR2GRAY);
    }

    float scale = 1;
    int row = leftimg.rows * scale;
    int col = leftimg.cols * scale;
    resize(leftimg, leftimg, Size( col, row));
    resize(rightimg,rightimg, Size(col, row));
    Mat depthleft = Mat ::zeros(row,col, CV_32S);
    Mat depthright = Mat ::zeros(row,col, CV_32S);
    Mat lastdisp = Mat ::zeros(row,col, CV_32S);
    int MaxDisparity = 60 * scale;
    int winsize = 31*scale;

    timebegin();
    GetPointDepthLeft(depthleft, leftimg, rightimg, MaxDisparity,  winsize);
    GetPointDepthRight(depthright, leftimg, rightimg, MaxDisparity,  winsize);
    CrossCheckDiaparity(depthleft,depthright, lastdisp, MaxDisparity, winsize);
    timeend("time ");

    MatDataNormal(depthleft,depthleft);
    MatDataNormal(depthright, depthright);
    MatDataNormal(lastdisp, lastdisp);
    namedWindow("left", 0);
    namedWindow("right", 0);
    namedWindow("depthleft", 0);
    namedWindow("depthright", 0);
    namedWindow("lastdisp",0);
    imshow("left", leftimg);
    imshow("right", rightimg);
    imshow("depthleft", depthleft);
    imshow("depthright", depthright);
    imshow("lastdisp",lastdisp);

    string strsave = "result_";
    imwrite(strsave +"depthleft.jpg", depthleft);
    imwrite(strsave +"depthright.jpg", depthright);
    imwrite(strsave +"lastdisp.jpg",lastdisp);
    waitKey(0);
    return 0;
}
复制代码



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值