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