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 #include "opencv2/photo/cuda.hpp" 46 #include "opencv2/core/private.cuda.hpp" 47 48 #include "opencv2/opencv_modules.hpp" 49 50 #ifdef HAVE_OPENCV_CUDAARITHM 51 # include "opencv2/cudaarithm.hpp" 52 #endif 53 54 #ifdef HAVE_OPENCV_CUDAIMGPROC 55 # include "opencv2/cudaimgproc.hpp" 56 #endif 57 58 using namespace cv; 59 using namespace cv::cuda; 60 61 #if !defined (HAVE_CUDA) || !defined(HAVE_OPENCV_CUDAARITHM) || !defined(HAVE_OPENCV_CUDAIMGPROC) 62 63 void cv::cuda::nonLocalMeans(InputArray, OutputArray, float, int, int, int, Stream&) { throw_no_cuda(); } 64 void cv::cuda::fastNlMeansDenoising(InputArray, OutputArray, float, int, int, Stream&) { throw_no_cuda(); } 65 void cv::cuda::fastNlMeansDenoisingColored(InputArray, OutputArray, float, float, int, int, Stream&) { throw_no_cuda(); } 66 67 #else 68 69 ////////////////////////////////////////////////////////////////////////////////// 70 //// Non Local Means Denosing (brute force) 71 72 namespace cv { namespace cuda { namespace device 73 { 74 namespace imgproc 75 { 76 template<typename T> 77 void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream); 78 } 79 }}} 80 81 void cv::cuda::nonLocalMeans(InputArray _src, OutputArray _dst, float h, int search_window, int block_window, int borderMode, Stream& stream) 82 { 83 using cv::cuda::device::imgproc::nlm_bruteforce_gpu; 84 typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream); 85 86 static const func_t funcs[4] = { nlm_bruteforce_gpu<uchar>, nlm_bruteforce_gpu<uchar2>, nlm_bruteforce_gpu<uchar3>, 0/*nlm_bruteforce_gpu<uchar4>,*/ }; 87 88 const GpuMat src = _src.getGpuMat(); 89 90 CV_Assert(src.type() == CV_8U || src.type() == CV_8UC2 || src.type() == CV_8UC3); 91 92 const func_t func = funcs[src.channels() - 1]; 93 CV_Assert(func != 0); 94 95 int b = borderMode; 96 CV_Assert(b == BORDER_REFLECT101 || b == BORDER_REPLICATE || b == BORDER_CONSTANT || b == BORDER_REFLECT || b == BORDER_WRAP); 97 98 _dst.create(src.size(), src.type()); 99 GpuMat dst = _dst.getGpuMat(); 100 101 func(src, dst, search_window/2, block_window/2, h, borderMode, StreamAccessor::getStream(stream)); 102 } 103 104 namespace cv { namespace cuda { namespace device 105 { 106 namespace imgproc 107 { 108 void nln_fast_get_buffer_size(const PtrStepSzb& src, int search_window, int block_window, int& buffer_cols, int& buffer_rows); 109 110 template<typename T> 111 void nlm_fast_gpu(const PtrStepSzb& src, PtrStepSzb dst, PtrStepi buffer, 112 int search_window, int block_window, float h, cudaStream_t stream); 113 114 void fnlm_split_channels(const PtrStepSz<uchar3>& lab, PtrStepb l, PtrStep<uchar2> ab, cudaStream_t stream); 115 void fnlm_merge_channels(const PtrStepb& l, const PtrStep<uchar2>& ab, PtrStepSz<uchar3> lab, cudaStream_t stream); 116 } 117 }}} 118 119 void cv::cuda::fastNlMeansDenoising(InputArray _src, OutputArray _dst, float h, int search_window, int block_window, Stream& stream) 120 { 121 const GpuMat src = _src.getGpuMat(); 122 123 CV_Assert(src.depth() == CV_8U && src.channels() < 4); 124 125 int border_size = search_window/2 + block_window/2; 126 Size esize = src.size() + Size(border_size, border_size) * 2; 127 128 BufferPool pool(stream); 129 130 GpuMat extended_src = pool.getBuffer(esize, src.type()); 131 cv::cuda::copyMakeBorder(src, extended_src, border_size, border_size, border_size, border_size, cv::BORDER_DEFAULT, Scalar(), stream); 132 GpuMat src_hdr = extended_src(Rect(Point2i(border_size, border_size), src.size())); 133 134 int bcols, brows; 135 device::imgproc::nln_fast_get_buffer_size(src_hdr, search_window, block_window, bcols, brows); 136 GpuMat buffer = pool.getBuffer(brows, bcols, CV_32S); 137 138 using namespace cv::cuda::device::imgproc; 139 typedef void (*nlm_fast_t)(const PtrStepSzb&, PtrStepSzb, PtrStepi, int, int, float, cudaStream_t); 140 static const nlm_fast_t funcs[] = { nlm_fast_gpu<uchar>, nlm_fast_gpu<uchar2>, nlm_fast_gpu<uchar3>, 0}; 141 142 _dst.create(src.size(), src.type()); 143 GpuMat dst = _dst.getGpuMat(); 144 145 funcs[src.channels()-1](src_hdr, dst, buffer, search_window, block_window, h, StreamAccessor::getStream(stream)); 146 } 147 148 void cv::cuda::fastNlMeansDenoisingColored(InputArray _src, OutputArray _dst, float h_luminance, float h_color, int search_window, int block_window, Stream& stream) 149 { 150 const GpuMat src = _src.getGpuMat(); 151 152 CV_Assert(src.type() == CV_8UC3); 153 154 BufferPool pool(stream); 155 156 GpuMat lab = pool.getBuffer(src.size(), src.type()); 157 cv::cuda::cvtColor(src, lab, cv::COLOR_BGR2Lab, 0, stream); 158 159 GpuMat l = pool.getBuffer(src.size(), CV_8U); 160 GpuMat ab = pool.getBuffer(src.size(), CV_8UC2); 161 device::imgproc::fnlm_split_channels(lab, l, ab, StreamAccessor::getStream(stream)); 162 163 fastNlMeansDenoising(l, l, h_luminance, search_window, block_window, stream); 164 fastNlMeansDenoising(ab, ab, h_color, search_window, block_window, stream); 165 166 device::imgproc::fnlm_merge_channels(l, ab, lab, StreamAccessor::getStream(stream)); 167 cv::cuda::cvtColor(lab, _dst, cv::COLOR_Lab2BGR, 0, stream); 168 } 169 170 #endif 171