disparity_filter

opencv_example
https://github.com/opencv/opencv_contrib/blob/master/modules/ximgproc/samples/disparity_filtering.cpp

#include "opencv2/calib3d.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/core/utility.hpp"
#include "opencv2/ximgproc/disparity_filter.hpp"
#include <iostream>
#include <string>
using namespace cv;
using namespace cv::ximgproc;
using namespace std;
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance);
const String keys =
"{help h usage ? | | print this message }"
"{@left |../data/aloeL.jpg | left view of the stereopair }"
"{@right |../data/aloeR.jpg | right view of the stereopair }"
"{GT |../data/aloeGT.png| optional ground-truth disparity (MPI-Sintel or Middlebury format) }"
"{dst_path |None | optional path to save the resulting filtered disparity map }"
"{dst_raw_path |None | optional path to save raw disparity map before filtering }"
"{algorithm |bm | stereo matching method (bm or sgbm) }"
"{filter |wls_conf | used post-filtering (wls_conf or wls_no_conf) }"
"{no-display | | don't display results }"
"{no-downscale | | force stereo matching on full-sized views to improve quality }"
"{dst_conf_path |None | optional path to save the confidence map used in filtering }"
"{vis_mult |1.0 | coefficient used to scale disparity map visualizations }"
"{max_disparity |160 | parameter of stereo matching }"
"{window_size |-1 | parameter of stereo matching }"
"{wls_lambda |8000.0 | parameter of post-filtering }"
"{wls_sigma |1.5 | parameter of post-filtering }"
;
int main(int argc, char** argv)
{
    CommandLineParser parser(argc, argv, keys);
    parser.about("Disparity Filtering Demo");
    if (parser.has("help"))
    {
        parser.printMessage();
        return 0;
    }
    String left_im = parser.get<String>(0);
    String right_im = parser.get<String>(1);
    String GT_path = parser.get<String>("GT");
    String dst_path = parser.get<String>("dst_path");
    String dst_raw_path = parser.get<String>("dst_raw_path");
    String dst_conf_path = parser.get<String>("dst_conf_path");
    String algo = parser.get<String>("algorithm");
    String filter = parser.get<String>("filter");
    bool no_display = parser.has("no-display");
    bool no_downscale = parser.has("no-downscale");
    int max_disp = parser.get<int>("max_disparity");
    double lambda = parser.get<double>("wls_lambda");
    double sigma = parser.get<double>("wls_sigma");
    double vis_mult = parser.get<double>("vis_mult");
    int wsize;
    if (parser.get<int>("window_size") >= 0) //user provided window_size value
        wsize = parser.get<int>("window_size");
    else
    {
        if (algo == "sgbm")
            wsize = 3; //default window size for SGBM
        else if (!no_downscale && algo == "bm" && filter == "wls_conf")
            wsize = 7; //default window size for BM on downscaled views (downscaling is performed only for wls_conf)
        else
            wsize = 15; //default window size for BM on full-sized views
    }
    if (!parser.check())
    {
        parser.printErrors();
        return -1;
    }
    //! [load_views]
    Mat left = imread(left_im, IMREAD_COLOR);
    if (left.empty())
    {
        cout << "Cannot read image file: " << left_im;
        return -1;
    }
    Mat right = imread(right_im, IMREAD_COLOR);
    if (right.empty())
    {
        cout << "Cannot read image file: " << right_im;
        return -1;
    }
    //! [load_views]
    bool noGT;
    Mat GT_disp;
    if (GT_path == "../data/aloeGT.png" && left_im != "../data/aloeL.jpg")
        noGT = true;
    else
    {
        noGT = false;
        if (readGT(GT_path, GT_disp) != 0)
        {
            cout << "Cannot read ground truth image file: " << GT_path << endl;
            return -1;
        }
    }
    Mat left_for_matcher, right_for_matcher;
    Mat left_disp, right_disp;
    Mat filtered_disp;
    Mat conf_map = Mat(left.rows, left.cols, CV_8U);
    conf_map = Scalar(255);
    Rect ROI;
    Ptr<DisparityWLSFilter> wls_filter;
    double matching_time, filtering_time;
    if (max_disp <= 0 || max_disp % 16 != 0)
    {
        cout << "Incorrect max_disparity value: it should be positive and divisible by 16";
        return -1;
    }
    if (wsize <= 0 || wsize % 2 != 1)
    {
        cout << "Incorrect window_size value: it should be positive and odd";
        return -1;
    }
    if (filter == "wls_conf") // filtering with confidence (significantly better quality than wls_no_conf)
    {
        if (!no_downscale)
        {
            // downscale the views to speed-up the matching stage, as we will need to compute both left
            // and right disparity maps for confidence map computation
            //! [downscale]
            max_disp /= 2;
            if (max_disp % 16 != 0)
                max_disp += 16 - (max_disp % 16);
            resize(left, left_for_matcher, Size(), 0.5, 0.5);
            resize(right, right_for_matcher, Size(), 0.5, 0.5);
            //! [downscale]
        }
        else
        {
            left_for_matcher = left.clone();
            right_for_matcher = right.clone();
        }
        if (algo == "bm")
        {
            //! [matching]
            Ptr<StereoBM> left_matcher = StereoBM::create(max_disp, wsize);
            wls_filter = createDisparityWLSFilter(left_matcher);
            Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
            cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
            cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
            matching_time = (double)getTickCount();
            left_matcher->compute(left_for_matcher, right_for_matcher, left_disp);
            right_matcher->compute(right_for_matcher, left_for_matcher, right_disp);
            matching_time = ((double)getTickCount() - matching_time) / getTickFrequency();
            //! [matching]
        }
        else if (algo == "sgbm")
        {
            Ptr<StereoSGBM> left_matcher = StereoSGBM::create(0, max_disp, wsize);
            left_matcher->setP1(24 * wsize*wsize);
            left_matcher->setP2(96 * wsize*wsize);
            left_matcher->setPreFilterCap(63);
            left_matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
            wls_filter = createDisparityWLSFilter(left_matcher);
            Ptr<StereoMatcher> right_matcher = createRightMatcher(left_matcher);
            matching_time = (double)getTickCount();
            left_matcher->compute(left_for_matcher, right_for_matcher, left_disp);
            right_matcher->compute(right_for_matcher, left_for_matcher, right_disp);
            matching_time = ((double)getTickCount() - matching_time) / getTickFrequency();
        }
        else
        {
            cout << "Unsupported algorithm";
            return -1;
        }
        //! [filtering]
        wls_filter->setLambda(lambda);
        wls_filter->setSigmaColor(sigma);
        filtering_time = (double)getTickCount();
        wls_filter->filter(left_disp, left, filtered_disp, right_disp);
        filtering_time = ((double)getTickCount() - filtering_time) / getTickFrequency();
        //! [filtering]
        conf_map = wls_filter->getConfidenceMap();
        // Get the ROI that was used in the last filter call:
        ROI = wls_filter->getROI();
        if (!no_downscale)
        {
            // upscale raw disparity and ROI back for a proper comparison:
            resize(left_disp, left_disp, Size(), 2.0, 2.0);
            left_disp = left_disp*2.0;
            ROI = Rect(ROI.x * 2, ROI.y * 2, ROI.width * 2, ROI.height * 2);
        }
    }
    else if (filter == "wls_no_conf")
    {
        /* There is no convenience function for the case of filtering with no confidence, so we
        will need to set the ROI and matcher parameters manually */
        left_for_matcher = left.clone();
        right_for_matcher = right.clone();
        if (algo == "bm")
        {
            Ptr<StereoBM> matcher = StereoBM::create(max_disp, wsize);
            matcher->setTextureThreshold(0);
            matcher->setUniquenessRatio(0);
            cvtColor(left_for_matcher, left_for_matcher, COLOR_BGR2GRAY);
            cvtColor(right_for_matcher, right_for_matcher, COLOR_BGR2GRAY);
            ROI = computeROI(left_for_matcher.size(), matcher);
            wls_filter = createDisparityWLSFilterGeneric(false);
            wls_filter->setDepthDiscontinuityRadius((int)ceil(0.33*wsize));
            matching_time = (double)getTickCount();
            matcher->compute(left_for_matcher, right_for_matcher, left_disp);
            matching_time = ((double)getTickCount() - matching_time) / getTickFrequency();
        }
        else if (algo == "sgbm")
        {
            Ptr<StereoSGBM> matcher = StereoSGBM::create(0, max_disp, wsize);
            matcher->setUniquenessRatio(0);
            matcher->setDisp12MaxDiff(1000000);
            matcher->setSpeckleWindowSize(0);
            matcher->setP1(24 * wsize*wsize);
            matcher->setP2(96 * wsize*wsize);
            matcher->setMode(StereoSGBM::MODE_SGBM_3WAY);
            ROI = computeROI(left_for_matcher.size(), matcher);
            wls_filter = createDisparityWLSFilterGeneric(false);
            wls_filter->setDepthDiscontinuityRadius((int)ceil(0.5*wsize));
            matching_time = (double)getTickCount();
            matcher->compute(left_for_matcher, right_for_matcher, left_disp);
            matching_time = ((double)getTickCount() - matching_time) / getTickFrequency();
        }
        else
        {
            cout << "Unsupported algorithm";
            return -1;
        }
        wls_filter->setLambda(lambda);
        wls_filter->setSigmaColor(sigma);
        filtering_time = (double)getTickCount();
        wls_filter->filter(left_disp, left, filtered_disp, Mat(), ROI);
        filtering_time = ((double)getTickCount() - filtering_time) / getTickFrequency();
    }
    else
    {
        cout << "Unsupported filter";
        return -1;
    }
    //collect and print all the stats:
    cout.precision(2);
    cout << "Matching time: " << matching_time << "s" << endl;
    cout << "Filtering time: " << filtering_time << "s" << endl;
    cout << endl;
    double MSE_before, percent_bad_before, MSE_after, percent_bad_after;
    if (!noGT)
    {
        MSE_before = computeMSE(GT_disp, left_disp, ROI);
        percent_bad_before = computeBadPixelPercent(GT_disp, left_disp, ROI);
        MSE_after = computeMSE(GT_disp, filtered_disp, ROI);
        percent_bad_after = computeBadPixelPercent(GT_disp, filtered_disp, ROI);
        cout.precision(5);
        cout << "MSE before filtering: " << MSE_before << endl;
        cout << "MSE after filtering: " << MSE_after << endl;
        cout << endl;
        cout.precision(3);
        cout << "Percent of bad pixels before filtering: " << percent_bad_before << endl;
        cout << "Percent of bad pixels after filtering: " << percent_bad_after << endl;
    }
    if (dst_path != "None")
    {
        Mat filtered_disp_vis;
        getDisparityVis(filtered_disp, filtered_disp_vis, vis_mult);
        imwrite(dst_path, filtered_disp_vis);
    }
    if (dst_raw_path != "None")
    {
        Mat raw_disp_vis;
        getDisparityVis(left_disp, raw_disp_vis, vis_mult);
        imwrite(dst_raw_path, raw_disp_vis);
    }
    if (dst_conf_path != "None")
    {
        imwrite(dst_conf_path, conf_map);
    }
    if (!no_display)
    {
        namedWindow("left", WINDOW_AUTOSIZE);
        imshow("left", left);
        namedWindow("right", WINDOW_AUTOSIZE);
        imshow("right", right);
        if (!noGT)
        {
            Mat GT_disp_vis;
            getDisparityVis(GT_disp, GT_disp_vis, vis_mult);
            namedWindow("ground-truth disparity", WINDOW_AUTOSIZE);
            imshow("ground-truth disparity", GT_disp_vis);
        }
        //! [visualization]
        Mat raw_disp_vis;
        getDisparityVis(left_disp, raw_disp_vis, vis_mult);
        namedWindow("raw disparity", WINDOW_AUTOSIZE);
        imshow("raw disparity", raw_disp_vis);
        Mat filtered_disp_vis;
        getDisparityVis(filtered_disp, filtered_disp_vis, vis_mult);
        namedWindow("filtered disparity", WINDOW_AUTOSIZE);
        imshow("filtered disparity", filtered_disp_vis);
        waitKey();
        //! [visualization]
    }
    return 0;
}
Rect computeROI(Size2i src_sz, Ptr<StereoMatcher> matcher_instance)
{
    int min_disparity = matcher_instance->getMinDisparity();
    int num_disparities = matcher_instance->getNumDisparities();
    int block_size = matcher_instance->getBlockSize();
    int bs2 = block_size / 2;
    int minD = min_disparity, maxD = min_disparity + num_disparities - 1;
    int xmin = maxD + bs2;
    int xmax = src_sz.width + minD - bs2;
    int ymin = bs2;
    int ymax = src_sz.height - bs2;
    Rect r(xmin, ymin, xmax - xmin, ymax - ymin);
    return r;
}

代码详解http://docs.opencv.org/3.1.0/d3/d14/tutorial_ximgproc_disparity_filtering.html
Introduction

Stereo matching algorithms, especially highly-optimized ones that are intended for real-time processing on CPU, tend to make quite a few errors on challenging sequences. These errors are usually concentrated in uniform texture-less areas, half-occlusions and regions near depth discontinuities. One way of dealing with stereo-matching errors is to use various techniques of detecting potentially inaccurate disparity values and invalidate them, therefore making the disparity map semi-sparse. Several such techniques are already implemented in the StereoBM and StereoSGBM algorithms. Another way would be to use some kind of filtering procedure to align the disparity map edges with those of the source image and to propagate the disparity values from high- to low-confidence regions like half-occlusions. Recent advances in edge-aware filtering have enabled performing such post-filtering under the constraints of real-time processing on CPU.

In this tutorial you will learn how to use the disparity map post-filtering to improve the results of StereoBM and StereoSGBM algorithms.

Source Stereoscopic Image

ambush_5_left.jpg
Left view
ambush_5_right.jpg
Right view
Source Code

We will be using snippets from the example application, that can be downloaded here.

Explanation

The provided example has several options that yield different trade-offs between the speed and the quality of the resulting disparity map. Both the speed and the quality are measured if the user has provided the ground-truth disparity map. In this tutorial we will take a detailed look at the default pipeline, that was designed to provide the best possible quality under the constraints of real-time processing on CPU.

Load left and right views
Mat left = imread(left_im ,IMREAD_COLOR);
if ( left.empty() )
{
cout<<”Cannot read image file: “<

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WLS(Weighted Least Squares)滤波器是一种基于图像的双边滤波器,它能够平衡平滑和边缘保留的效果。在 OpenCV 中,可以使用 `cv2.ximgproc.createDisparityWLSFilter` 函数来创建一个 WLS 滤波器对象。 以下是一个使用 WLS 滤波器的示例代码: ``` python import cv2 # 读取左右视图图像和视差图 imgL = cv2.imread('left.png', 0) imgR = cv2.imread('right.png', 0) disp = cv2.imread('disp.png', 0) # 创建 WLS 滤波器对象 wls_filter = cv2.ximgproc.createDisparityWLSFilter(left_matcher) # 设置 WLS 滤波器参数 wls_filter.setLambda(80000) wls_filter.setSigmaColor(1.5) # 应用 WLS 滤波器 filtered_disp = wls_filter.filter(disp, imgL, None, imgR) # 显示结果 cv2.imshow('Filtered Disparity', filtered_disp) cv2.waitKey() cv2.destroyAllWindows() ``` 在上面的代码中,首先读取了左右视图图像和视差图。然后,创建了一个 WLS 滤波器对象。接着,设置了 WLS 滤波器的参数,包括 Lambda 和 SigmaColor。最后,使用 `filter` 函数对视差图进行滤波,并显示结果。 需要注意的是,在使用 WLS 滤波器时,需要先使用立体匹配算法(如 SGBM 或 BM)计算出视差图。函数 `cv2.ximgproc.createDisparityWLSFilter` 的第一个参数就是立体匹配算法对象。在示例代码中,我们将 `left_matcher` 作为参数传递给了该函数。如果你使用的是 BM 算法,则可以使用 `cv2.StereoBM_create` 函数创建一个 BM 算法对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值