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