SGBM原理和opencv编程

算法原理

先给出一个画的很好的流程图:
SGBM原理和opencv编程_第1张图片

具体的算法原理请移步opencvSGBM半全局立体匹配算法的研究(1)

代码及结果

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
using namespace cv;

int main() {

    //读图
    Mat left_img = imread("D:\\学习资料\\C++\\C++ code\\semiglobalmatching-master\\Data\\Teddy\\im2.png", 0);
    Mat right_img = imread("D:\\学习资料\\C++\\C++ code\\semiglobalmatching-master\\Data\\Teddy\\im6.png", 0);

    //创建SGBM对象
    int mindisparity = 0;
    int ndisparities = 64;
    int SADWindowSize = 9;
    Ptr<StereoSGBM> sgbm = StereoSGBM::create(mindisparity, ndisparities, SADWindowSize);

    //设置SGBM参数
    int P1 = 8 * left_img.channels() * SADWindowSize * SADWindowSize;
    int P2 = 32 * left_img.channels() * SADWindowSize * SADWindowSize;
    sgbm->setP1(P1);
    sgbm->setP2(P2);
    sgbm->setPreFilterCap(15);
    sgbm->setUniquenessRatio(10);
    sgbm->setSpeckleRange(2);
    sgbm->setSpeckleWindowSize(50);
    sgbm->setDisp12MaxDiff(1);
    sgbm->setMode(cv::StereoSGBM::MODE_HH);

    //计算视差
    Mat disp;
    sgbm->compute(left_img, right_img, disp);
    disp.convertTo(disp, CV_32F, 1.0 / 16);  //除以16得到真实视差图

    //视差图显示
    Mat disp8U = Mat(disp.rows, disp.cols, CV_8UC1);
    disp.convertTo(disp8U, CV_8UC1, 255. / ndisparities);
    //normalize(disp, disp8U, 0, 255, NORM_MINMAX, CV_8UC1);  //这种归一化的方法是错误的,误匹配率为99%
    
    imshow("disparity", disp8U);
    waitKey(0);
    imwrite("output_disparity.png", disp8U);


    system("pause");
    return 0;
}

上面是sgbm的代码,然后我们来看一下结果视差图的显示:

SGBM原理和opencv编程_第2张图片
然后看一下Ground truth:
SGBM原理和opencv编程_第3张图片
有了真实的视差图和计算视差图之后,我们自然要看看sgbm算法的误匹配率是多少。

#include 
#include 
#include 

using namespace std;
using namespace cv;

int main(int argc, char** argv) {

    cv::Mat GT;
    cv::Mat output_disparity;
    Mat occl, occ_and_discont, occ_and_textl;
    GT = cv::imread("D:\\学习资料\\C++\\C++ code\\semiglobalmatching-master\\Data\\Teddy\\disp2.png", CV_LOAD_IMAGE_GRAYSCALE);
    output_disparity = cv::imread("D:\\学习资料\\C++\\C++ code\\SGBM\\SGBM\\output_disparity.png", CV_LOAD_IMAGE_GRAYSCALE);
    occl = imread("D:\\学习资料\\C++\\C++ code\\middleburry_dataset\\occl.png", CV_LOAD_IMAGE_GRAYSCALE);
    occ_and_discont = imread("D:\\学习资料\\C++\\C++ code\\middleburry_dataset\\occ_and_discont.png", CV_LOAD_IMAGE_GRAYSCALE);
    occ_and_textl = imread("D:\\学习资料\\C++\\C++ code\\middleburry_dataset\\occ_and_textl.png", CV_LOAD_IMAGE_GRAYSCALE);

    if (!GT.data || !output_disparity.data || !occl.data || !occ_and_discont.data || !occ_and_textl.data) {
        std::cerr << "Could not open or find one of the images!" << std::endl;
        return -1;
    }

    if (GT.rows != output_disparity.rows || GT.cols != output_disparity.cols || GT.rows != occl.rows || GT.cols != occl.cols
        || GT.rows != occ_and_discont.rows || GT.cols != occ_and_discont.cols || GT.rows != occ_and_textl.rows
        || GT.cols != occ_and_textl.cols) {
        std::cerr << "Error: The images have different dimensions!" << std::endl;
        return -2;
    }

    unsigned long all, nonoccl, discont, textl;
    unsigned long all_counter, nonoccl_counter, discont_counter, textl_counter;
    all = nonoccl = discont = textl = all_counter = nonoccl_counter = discont_counter = textl_counter = 0;
    for (int row = 0; row < GT.rows; ++row) {
        for (int col = 0; col < GT.cols; ++col) {
            //统计总体的误匹配率
            if (GT.at<uchar>(row, col) != 0) {
                all_counter++;
                if (abs(GT.at<uchar>(row, col) - output_disparity.at<uchar>(row, col)) > 4) {
                    all++;
                }
            }
            //统计非遮挡的误匹配率
            if (occl.at<uchar>(row, col) != 0) {
                nonoccl_counter++;
                if (abs(GT.at<uchar>(row, col) - output_disparity.at<uchar>(row, col)) > 4) {
                    nonoccl++;
                }
            }
            //统计深度不连续的误匹配率
            if (occ_and_discont.at<uchar>(row, col) == 255) {
                discont_counter++;
                if (abs(GT.at<uchar>(row, col) - output_disparity.at<uchar>(row, col)) > 4) {
                    discont++;
                }
            }
            //统计无纹理的误匹配率
            if (occ_and_textl.at<uchar>(row, col) == 255) {
                textl_counter++;
                if (abs(GT.at<uchar>(row, col) - output_disparity.at<uchar>(row, col)) > 4) {
                    textl;
                }
            }

        }
    }
    cout << "rows * cols = " << GT.rows * GT.cols << endl;
    cout << "all_counter = " << all_counter << endl;
    cout << "all = " << all << endl;
    cout << "ALL errer: ";
    std::cout << 100 * double(all / double(all_counter)) << "%" << endl;
    cout << endl;

    cout << "nonoccl_counter = " << nonoccl_counter << endl;
    cout << "nonoccl = " << nonoccl << endl;
    cout << "nonoccl errer: ";
    std::cout << 100 * double(nonoccl / double(nonoccl_counter)) << "%" << endl;
    cout << endl;

    cout << "discont_counter = " << discont_counter << endl;
    cout << "discont = " << discont << endl;
    cout << "discont errer: ";
    std::cout << 100 * double(discont / double(discont_counter)) << "%" << endl;
    cout << endl;

    cout << "textl_counter = " << textl_counter << endl;
    cout << "textl = " << textl << endl;
    cout << "textl errer: ";
    std::cout << 100 * double(textl / double(textl_counter)) << "%" << endl;

    system("pause");
    return 0;
}

rows * cols = 168750
all_counter = 165344
all = 46198
ALL errer: 27.9405%

nonoccl_counter = 147651
nonoccl = 29056
nonoccl errer: 19.6788%

discont_counter = 40517
discont = 14778
discont errer: 36.4736%

textl_counter = 18081
textl = 0
textl errer: 0%

总体的误匹配率是28%,可以看到误匹配率还是挺高的。经过参数调整之后,该数值变化不大。

你可能感兴趣的:(传统双目,+,结构光)