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 
createDisparityBilateralFilter(int,int,int)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 
getNumDisparities() const65         int getNumDisparities() const { return ndisp_; }
setNumDisparities(int numDisparities)66         void setNumDisparities(int numDisparities) { ndisp_ = numDisparities; }
67 
getRadius() const68         int getRadius() const { return radius_; }
69         void setRadius(int radius);
70 
getNumIters() const71         int getNumIters() const { return iters_; }
setNumIters(int iters)72         void setNumIters(int iters) { iters_ = iters; }
73 
getEdgeThreshold() const74         double getEdgeThreshold() const { return edge_threshold_; }
setEdgeThreshold(double edge_threshold)75         void setEdgeThreshold(double edge_threshold) { edge_threshold_ = (float) edge_threshold; }
76 
getMaxDiscThreshold() const77         double getMaxDiscThreshold() const { return max_disc_threshold_; }
setMaxDiscThreshold(double max_disc_threshold)78         void setMaxDiscThreshold(double max_disc_threshold) { max_disc_threshold_ = (float) max_disc_threshold; }
79 
getSigmaRange() const80         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 
calc_color_weighted_table(GpuMat & table_color,float sigma_range,int len)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 
calc_space_weighted_filter(GpuMat & table_space,int win_size,float dist_space)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 
DispBilateralFilterImpl(int ndisp,int radius,int iters)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 
setRadius(int radius)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 
setSigmaRange(double sigma_range)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>
disp_bilateral_filter_operator(int ndisp,int radius,int iters,float edge_threshold,float max_disc_threshold,GpuMat & table_color,GpuMat & table_space,const GpuMat & disp,const GpuMat & img,OutputArray _dst,Stream & stream)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 
apply(InputArray _disp,InputArray _image,OutputArray dst,Stream & stream)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 
createDisparityBilateralFilter(int ndisp,int radius,int iters)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