DisparityCostVolumeEstimator.cpp

weixin_33816946發表於2018-07-10

 

#include "DisparityCostVolumeEstimator.hpp"

#include "DisparityCostVolume.hpp"

#include "stereo_matching/cost_functions.hpp"

#include "helpers/get_option_value.hpp"
#include "helpers/fill_multi_array.hpp"

#include <boost/gil/image_view_factory.hpp>

namespace doppia
{

using namespace boost;
using namespace boost::gil;
using namespace std;

typedef DisparityCostVolume::range_t range_t;
typedef DisparityCostVolume::const_data_2d_view_t const_data_2d_view_t;
typedef DisparityCostVolume::const_data_1d_view_t const_data_1d_view_t;
typedef DisparityCostVolume::const_data_2d_subarray_t const_data_2d_subarray_t;
typedef DisparityCostVolume::const_data_1d_subarray_t const_data_1d_subarray_t;
typedef DisparityCostVolume::data_3d_view_t data_3d_view_t;


program_options::options_description  DisparityCostVolumeEstimator::get_args_options()
{
    program_options::options_description desc("DisparityCostVolumeEstimator options");

    const bool simple_block_matcher_options_are_included = true;

    if(not simple_block_matcher_options_are_included)
    {
        desc.add_options()

                ("pixels_matching",
                 program_options::value<string>()->default_value("sad"),
                 "pixels matching method: sad, ssd, census or gradient")

                ("threshold",
                 program_options::value<float>()->default_value(0.5),
                 "minimum percent of pixels required to declare a match value between [0,1]")

                ;
    }

    return desc;
}

DisparityCostVolumeEstimator::DisparityCostVolumeEstimator()
    : AbstractDisparityCostVolumeEstimator()
{
    // this constructor should only be used for unit testing
    return;
}

DisparityCostVolumeEstimator::DisparityCostVolumeEstimator(const program_options::variables_map &options)
    : AbstractDisparityCostVolumeEstimator(options)
{

    threshold_percent = get_option_value<float>(options,"threshold");

    assert(threshold_percent > 0.0f);
    assert(threshold_percent <= 1.0f);

    return;
}

DisparityCostVolumeEstimator::~DisparityCostVolumeEstimator()
{
    // nothing to do here
    return;
}


void  DisparityCostVolumeEstimator::compute(gil::gray8c_view_t &left,
                                            gil::gray8c_view_t &right,
                                            DisparityCostVolume &cost_volume)
{
    compute_impl(left, right, cost_volume);
    return;
}

void  DisparityCostVolumeEstimator::compute(gil::rgb8c_view_t  &left,
                                            gil::rgb8c_view_t &right,
                                            DisparityCostVolume &cost_volume)
{
    compute_impl(left, right, cost_volume);
    return;
}


template <typename ImgView>
void DisparityCostVolumeEstimator::compute_impl( ImgView &left, ImgView &right, DisparityCostVolume &cost_volume)
{

    if (pixels_matching_method == "sad")
    {
        if(first_computation)
        {
            printf("DisparityCostVolumeEstimator::compute_impl will use sad matching over %zi disparities\n\n",
                   max_disparity);
        }
        SadCostFunctionT<uint8_t> pixels_distance;
        compute_costs_impl(left, right, pixels_distance, cost_volume);
    }
    else if (pixels_matching_method == "ssd")
    {
        if(first_computation)
        {
            printf("DisparityCostVolumeEstimator::compute_impl will use ssd matching over %zi disparities\n\n",
                   max_disparity);
        }
        SsdCostFunction pixels_distance;
        compute_costs_impl(left, right, pixels_distance, cost_volume);
    }
    else
    {
        printf("DisparityCostVolumeEstimator::compute_impl received an unknow pixels_matching_method value == %s\n",
               pixels_matching_method.c_str());

        throw std::invalid_argument("DisparityCostVolumeEstimator::compute_impl received an unknow pixels_matching_method");
    }

    first_computation = false;

    return;
}




template <typename ImgView, typename PixelsCostType>
inline void compute_costs_for_disparity(const ImgView &left, const ImgView &right,
                                        PixelsCostType &pixels_distance,
                                        const int disparity,
                                        DisparityCostVolume::data_2d_view_t &disparity_cost_view)
{
    typedef typename ImgView::value_type pixel_t;
    typedef  DisparityCostVolume::data_1d_subarray_t data_1d_subarray_t;

    // a pixel (x,y) on the left image should be matched on the right image on the range ([0,x],y)
    //const int first_right_x = first_left_x - disparity;

    for(int y=0; y < left.height(); y+=1)
    {
        typename ImgView::x_iterator left_row_it = left.x_at(disparity, y);
        typename ImgView::x_iterator right_row_it = right.row_begin(y);
        data_1d_subarray_t cost_row_subarray = disparity_cost_view[y];
        data_1d_subarray_t::iterator cost_it = cost_row_subarray.begin() + disparity;
        for(int left_x=disparity; left_x < left.width(); left_x+=1, ++left_row_it, ++right_row_it, ++cost_it)
        {
            const DisparityCostVolume::cost_t pixel_cost = pixels_distance(*left_row_it, *right_row_it);
            *cost_it = pixel_cost;
        } // end of 'for each row'
    } // end of 'for each column'

    return;
}



template <typename ImgView, typename PixelsCostType>
void DisparityCostVolumeEstimator::compute_costs_impl(const ImgView &left, const ImgView &right,
                                                      PixelsCostType &pixels_distance,
                                                      DisparityCostVolume &cost_volume)
{

    typedef typename ImgView::value_type pixel_t;
    maximum_cost_per_pixel = pixels_distance.template get_maximum_cost_per_pixel<pixel_t>();

    // lazy initialization
    this->resize_cost_volume(left.dimensions(), cost_volume);

    const bool crop_borders = false;

    if(crop_borders)
    {
        // FIXME hardcoded values
        const int top_bottom_margin = 25; // 20 // 10 // pixels
        const int left_right_margin = 40; //left.width()*0.1;  // *0.05 // pixels

        const int
                sub_width = left.width() - 2*left_right_margin,
                sub_height = left.height() - 2*top_bottom_margin;
        const ImgView
                left_subview = boost::gil::subimage_view(left,
                                                         left_right_margin, top_bottom_margin,
                                                         sub_width, sub_height),
                right_subview = boost::gil::subimage_view(right,
                                                          left_right_margin,top_bottom_margin,
                                                          sub_width, sub_height);


        const int y_min = top_bottom_margin, y_max = left.height() - top_bottom_margin;
        const int x_min = left_right_margin, x_max = left.width() - left_right_margin;
        data_3d_view_t data = cost_volume.get_costs_views();
        data_3d_view_t
                data_subview = data[ boost::indices[range_t(y_min, y_max)][range_t(x_min, x_max)][range_t()] ];

        // fill the original volumn with zero
        fill(cost_volume.get_costs_views(), 0);

#pragma omp parallel for
        for(size_t disparity=0; disparity < max_disparity; disparity +=1)
        {
            DisparityCostVolume::data_2d_view_t disparity_slice = data_subview[ boost::indices[range_t()][range_t()][disparity] ];
            compute_costs_for_disparity(left_subview, right_subview, pixels_distance, disparity, disparity_slice);
        }

    }
    else
    {

        // for each pixel and each disparity value
#pragma omp parallel for
        for(size_t disparity=0; disparity < max_disparity; disparity +=1)
        {
            data_3d_view_t data = cost_volume.get_costs_views();
            DisparityCostVolume::data_2d_view_t disparity_slice = data[ boost::indices[range_t()][range_t()][disparity] ];
            compute_costs_for_disparity(left, right, pixels_distance, disparity, disparity_slice);
        }

    } // end of "if else crop_borders"

    return;
}



} // end of namespace doppia

ImgView這個模版類沒有找到

SsdCostFunction、SadCostFunctionT來自cost_functions.hpp,實際上就是具體值怎麼計算