Home | History | Annotate | Download | only in src
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #include "precomp.hpp"
     44 
     45 using namespace cv;
     46 using namespace cv::cuda;
     47 
     48 #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER)
     49 
     50 Ptr<cuda::DisparityBilateralFilter> cv::cuda::createDisparityBilateralFilter(int, int, int) { throw_no_cuda(); return Ptr<cuda::DisparityBilateralFilter>(); }
     51 
     52 #else /* !defined (HAVE_CUDA) */
     53 
     54 #include "cuda/disparity_bilateral_filter.hpp"
     55 
     56 namespace
     57 {
     58     class DispBilateralFilterImpl : public cuda::DisparityBilateralFilter
     59     {
     60     public:
     61         DispBilateralFilterImpl(int ndisp, int radius, int iters);
     62 
     63         void apply(InputArray disparity, InputArray image, OutputArray dst, Stream& stream);
     64 
     65         int getNumDisparities() const { return ndisp_; }
     66         void setNumDisparities(int numDisparities) { ndisp_ = numDisparities; }
     67 
     68         int getRadius() const { return radius_; }
     69         void setRadius(int radius);
     70 
     71         int getNumIters() const { return iters_; }
     72         void setNumIters(int iters) { iters_ = iters; }
     73 
     74         double getEdgeThreshold() const { return edge_threshold_; }
     75         void setEdgeThreshold(double edge_threshold) { edge_threshold_ = (float) edge_threshold; }
     76 
     77         double getMaxDiscThreshold() const { return max_disc_threshold_; }
     78         void setMaxDiscThreshold(double max_disc_threshold) { max_disc_threshold_ = (float) max_disc_threshold; }
     79 
     80         double getSigmaRange() const { return sigma_range_; }
     81         void setSigmaRange(double sigma_range);
     82 
     83     private:
     84         int ndisp_;
     85         int radius_;
     86         int iters_;
     87         float edge_threshold_;
     88         float max_disc_threshold_;
     89         float sigma_range_;
     90 
     91         GpuMat table_color_;
     92         GpuMat table_space_;
     93     };
     94 
     95     void calc_color_weighted_table(GpuMat& table_color, float sigma_range, int len)
     96     {
     97         Mat cpu_table_color(1, len, CV_32F);
     98 
     99         float* line = cpu_table_color.ptr<float>();
    100 
    101         for(int i = 0; i < len; i++)
    102             line[i] = static_cast<float>(std::exp(-double(i * i) / (2 * sigma_range * sigma_range)));
    103 
    104         table_color.upload(cpu_table_color);
    105     }
    106 
    107     void calc_space_weighted_filter(GpuMat& table_space, int win_size, float dist_space)
    108     {
    109         int half = (win_size >> 1);
    110 
    111         Mat cpu_table_space(half + 1, half + 1, CV_32F);
    112 
    113         for (int y = 0; y <= half; ++y)
    114         {
    115             float* row = cpu_table_space.ptr<float>(y);
    116             for (int x = 0; x <= half; ++x)
    117                 row[x] = exp(-sqrt(float(y * y) + float(x * x)) / dist_space);
    118         }
    119 
    120         table_space.upload(cpu_table_space);
    121     }
    122 
    123     const float DEFAULT_EDGE_THRESHOLD = 0.1f;
    124     const float DEFAULT_MAX_DISC_THRESHOLD = 0.2f;
    125     const float DEFAULT_SIGMA_RANGE = 10.0f;
    126 
    127     DispBilateralFilterImpl::DispBilateralFilterImpl(int ndisp, int radius, int iters) :
    128         ndisp_(ndisp), radius_(radius), iters_(iters),
    129         edge_threshold_(DEFAULT_EDGE_THRESHOLD), max_disc_threshold_(DEFAULT_MAX_DISC_THRESHOLD),
    130         sigma_range_(DEFAULT_SIGMA_RANGE)
    131     {
    132         calc_color_weighted_table(table_color_, sigma_range_, 255);
    133         calc_space_weighted_filter(table_space_, radius_ * 2 + 1, radius_ + 1.0f);
    134     }
    135 
    136     void DispBilateralFilterImpl::setRadius(int radius)
    137     {
    138         radius_ = radius;
    139         calc_space_weighted_filter(table_space_, radius_ * 2 + 1, radius_ + 1.0f);
    140     }
    141 
    142     void DispBilateralFilterImpl::setSigmaRange(double sigma_range)
    143     {
    144         sigma_range_ = (float) sigma_range;
    145         calc_color_weighted_table(table_color_, sigma_range_, 255);
    146     }
    147 
    148     template <typename T>
    149     void disp_bilateral_filter_operator(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold,
    150                                         GpuMat& table_color, GpuMat& table_space,
    151                                         const GpuMat& disp, const GpuMat& img,
    152                                         OutputArray _dst, Stream& stream)
    153     {
    154         using namespace cv::cuda::device::disp_bilateral_filter;
    155 
    156         const short edge_disc = std::max<short>(short(1), short(ndisp * edge_threshold + 0.5));
    157         const short max_disc = short(ndisp * max_disc_threshold + 0.5);
    158 
    159         size_t table_space_step = table_space.step / sizeof(float);
    160 
    161         _dst.create(disp.size(), disp.type());
    162         GpuMat dst = _dst.getGpuMat();
    163 
    164         if (dst.data != disp.data)
    165             disp.copyTo(dst, stream);
    166 
    167         disp_bilateral_filter<T>(dst, img, img.channels(), iters, table_color.ptr<float>(), (float *)table_space.data, table_space_step, radius, edge_disc, max_disc, StreamAccessor::getStream(stream));
    168     }
    169 
    170     void DispBilateralFilterImpl::apply(InputArray _disp, InputArray _image, OutputArray dst, Stream& stream)
    171     {
    172         typedef void (*bilateral_filter_operator_t)(int ndisp, int radius, int iters, float edge_threshold, float max_disc_threshold,
    173                                                     GpuMat& table_color, GpuMat& table_space,
    174                                                     const GpuMat& disp, const GpuMat& img, OutputArray dst, Stream& stream);
    175         const bilateral_filter_operator_t operators[] =
    176             {disp_bilateral_filter_operator<unsigned char>, 0, 0, disp_bilateral_filter_operator<short>, 0, 0, 0, 0};
    177 
    178         CV_Assert( 0 < ndisp_ && 0 < radius_ && 0 < iters_ );
    179 
    180         GpuMat disp = _disp.getGpuMat();
    181         GpuMat img = _image.getGpuMat();
    182 
    183         CV_Assert( disp.type() == CV_8U || disp.type() == CV_16S );
    184         CV_Assert( img.type() == CV_8UC1 || img.type() == CV_8UC3 );
    185         CV_Assert( disp.size() == img.size() );
    186 
    187         operators[disp.type()](ndisp_, radius_, iters_, edge_threshold_, max_disc_threshold_,
    188                                table_color_, table_space_, disp, img, dst, stream);
    189     }
    190 }
    191 
    192 Ptr<cuda::DisparityBilateralFilter> cv::cuda::createDisparityBilateralFilter(int ndisp, int radius, int iters)
    193 {
    194     return makePtr<DispBilateralFilterImpl>(ndisp, radius, iters);
    195 }
    196 
    197 #endif /* !defined (HAVE_CUDA) */
    198