From e72ba73e708537686218bfdd35a1214a0ccdd9b4 Mon Sep 17 00:00:00 2001 From: Vladislav Vinogradov Date: Wed, 17 Apr 2013 18:20:18 +0400 Subject: [PATCH] moved gpu nlm to photo module --- modules/gpuimgproc/CMakeLists.txt | 2 +- modules/gpuimgproc/doc/image_processing.rst | 100 +-------------------- modules/gpuimgproc/include/opencv2/gpuimgproc.hpp | 19 ---- modules/gpuimgproc/perf/perf_imgproc.cpp | 46 ++++++++++ modules/gpuimgproc/perf/perf_precomp.hpp | 2 - modules/gpuimgproc/src/bilateral_filter.cpp | 99 ++++++++++++++++++++ modules/gpuimgproc/test/test_imgproc.cpp | 2 +- modules/photo/CMakeLists.txt | 2 +- modules/photo/doc/denoising.rst | 99 ++++++++++++++++++++ modules/photo/include/opencv2/photo/gpu.hpp | 71 +++++++++++++++ .../perf_denoising.cpp => photo/perf/perf_gpu.cpp} | 49 +--------- modules/{gpuimgproc => photo}/src/cuda/nlm.cu | 0 .../denoising.cpp => photo/src/denoising_gpu.cpp} | 52 ++--------- .../test/test_denoising_gpu.cpp} | 34 ++----- 14 files changed, 332 insertions(+), 245 deletions(-) create mode 100644 modules/gpuimgproc/src/bilateral_filter.cpp create mode 100644 modules/photo/include/opencv2/photo/gpu.hpp rename modules/{gpuimgproc/perf/perf_denoising.cpp => photo/perf/perf_gpu.cpp} (82%) rename modules/{gpuimgproc => photo}/src/cuda/nlm.cu (100%) rename modules/{gpuimgproc/src/denoising.cpp => photo/src/denoising_gpu.cpp} (72%) rename modules/{gpuimgproc/test/test_denoising.cpp => photo/test/test_denoising_gpu.cpp} (85%) diff --git a/modules/gpuimgproc/CMakeLists.txt b/modules/gpuimgproc/CMakeLists.txt index 04a31d5..19a66dc 100644 --- a/modules/gpuimgproc/CMakeLists.txt +++ b/modules/gpuimgproc/CMakeLists.txt @@ -6,4 +6,4 @@ set(the_description "GPU-accelerated Image Processing") ocv_warnings_disable(CMAKE_CXX_FLAGS -Wundef -Wmissing-declarations -Wshadow -Wunused-parameter) -ocv_define_module(gpuimgproc opencv_imgproc opencv_gpuarithm opencv_gpufilters OPTIONAL opencv_photo) +ocv_define_module(gpuimgproc opencv_imgproc opencv_gpuarithm opencv_gpufilters) diff --git a/modules/gpuimgproc/doc/image_processing.rst b/modules/gpuimgproc/doc/image_processing.rst index 52d7b92..fed3aaf 100644 --- a/modules/gpuimgproc/doc/image_processing.rst +++ b/modules/gpuimgproc/doc/image_processing.rst @@ -397,105 +397,7 @@ Performs bilateral filtering of passed image .. seealso:: - :ocv:func:`bilateralFilter`, - - -gpu::nonLocalMeans -------------------- -Performs pure non local means denoising without any simplification, and thus it is not fast. - -.. ocv:function:: void gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()) - - :param src: Source image. Supports only CV_8UC1, CV_8UC2 and CV_8UC3. - - :param dst: Destination image. - - :param h: Filter sigma regulating filter strength for color. - - :param search_window: Size of search window. - - :param block_size: Size of block used for computing weights. - - :param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. - - :param stream: Stream for the asynchronous version. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoising` - - - -gpu::FastNonLocalMeansDenoising -------------------------------- -.. ocv:class:: gpu::FastNonLocalMeansDenoising - - :: - - class FastNonLocalMeansDenoising - { - public: - //! Simple method, recommended for grayscale images (though it supports multichannel images) - void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - //! Processes luminance and color components separatelly - void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - }; - -The class implements fast approximate Non Local Means Denoising algorithm. - - - -gpu::FastNonLocalMeansDenoising::simpleMethod() ------------------------------------------------ -Perform image denoising using Non-local Means Denoising algorithm http://www.ipol.im/pub/algo/bcm_non_local_means_denoising with several computational optimizations. Noise expected to be a gaussian white noise - -.. ocv:function:: void gpu::FastNonLocalMeansDenoising::simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - - :param src: Input 8-bit 1-channel, 2-channel or 3-channel image. - - :param dst: Output image with the same size and type as ``src`` . - - :param h: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise - - :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels - - :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - - :param stream: Stream for the asynchronous invocations. - -This function expected to be applied to grayscale images. For colored images look at ``FastNonLocalMeansDenoising::labMethod``. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoising` - - - -gpu::FastNonLocalMeansDenoising::labMethod() --------------------------------------------- -Modification of ``FastNonLocalMeansDenoising::simpleMethod`` for color images - -.. ocv:function:: void gpu::FastNonLocalMeansDenoising::labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) - - :param src: Input 8-bit 3-channel image. - - :param dst: Output image with the same size and type as ``src`` . - - :param h_luminance: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise - - :param float: The same as h but for color components. For most images value equals 10 will be enought to remove colored noise and do not distort colors - - :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels - - :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels - - :param stream: Stream for the asynchronous invocations. - -The function converts image to CIELAB colorspace and then separately denoise L and AB components with given h parameters using ``FastNonLocalMeansDenoising::simpleMethod`` function. - -.. seealso:: - - :ocv:func:`fastNlMeansDenoisingColored` + :ocv:func:`bilateralFilter` diff --git a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp index 00ef0a3..8d15334 100644 --- a/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp +++ b/modules/gpuimgproc/include/opencv2/gpuimgproc.hpp @@ -143,25 +143,6 @@ CV_EXPORTS void blendLinear(const GpuMat& img1, const GpuMat& img2, const GpuMat CV_EXPORTS void bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode = BORDER_DEFAULT, Stream& stream = Stream::Null()); -//! Brute force non-local means algorith (slow but universal) -CV_EXPORTS void nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()); - -//! Fast (but approximate)version of non-local means algorith similar to CPU function (running sums technique) -class CV_EXPORTS FastNonLocalMeansDenoising -{ -public: - //! Simple method, recommended for grayscale images (though it supports multichannel images) - void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); - - //! Processes luminance and color components separatelly - void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); - -private: - - GpuMat buffer, extended_src_buffer; - GpuMat lab, l, ab; -}; - struct CV_EXPORTS CannyBuf { void create(const Size& image_size, int apperture_size = 3); diff --git a/modules/gpuimgproc/perf/perf_imgproc.cpp b/modules/gpuimgproc/perf/perf_imgproc.cpp index ff19e14..73e2988 100644 --- a/modules/gpuimgproc/perf/perf_imgproc.cpp +++ b/modules/gpuimgproc/perf/perf_imgproc.cpp @@ -1046,3 +1046,49 @@ PERF_TEST_P(Method_Sz, GeneralizedHough, CPU_SANITY_CHECK(positions); } } + +////////////////////////////////////////////////////////////////////// +// BilateralFilter + +DEF_PARAM_TEST(Sz_Depth_Cn_KernelSz, cv::Size, MatDepth, MatCn, int); + +PERF_TEST_P(Sz_Depth_Cn_KernelSz, BilateralFilter, + Combine(GPU_TYPICAL_MAT_SIZES, + Values(CV_8U, CV_32F), + GPU_CHANNELS_1_3, + Values(3, 5, 9))) +{ + declare.time(60.0); + + const cv::Size size = GET_PARAM(0); + const int depth = GET_PARAM(1); + const int channels = GET_PARAM(2); + const int kernel_size = GET_PARAM(3); + + const float sigma_color = 7; + const float sigma_spatial = 5; + const int borderMode = cv::BORDER_REFLECT101; + + const int type = CV_MAKE_TYPE(depth, channels); + + cv::Mat src(size, type); + declare.in(src, WARMUP_RNG); + + if (PERF_RUN_GPU()) + { + const cv::gpu::GpuMat d_src(src); + cv::gpu::GpuMat dst; + + TEST_CYCLE() cv::gpu::bilateralFilter(d_src, dst, kernel_size, sigma_color, sigma_spatial, borderMode); + + GPU_SANITY_CHECK(dst); + } + else + { + cv::Mat dst; + + TEST_CYCLE() cv::bilateralFilter(src, dst, kernel_size, sigma_color, sigma_spatial, borderMode); + + CPU_SANITY_CHECK(dst); + } +} diff --git a/modules/gpuimgproc/perf/perf_precomp.hpp b/modules/gpuimgproc/perf/perf_precomp.hpp index 6ecb958..adaa4eb 100644 --- a/modules/gpuimgproc/perf/perf_precomp.hpp +++ b/modules/gpuimgproc/perf/perf_precomp.hpp @@ -57,8 +57,6 @@ #include "opencv2/gpuimgproc.hpp" #include "opencv2/imgproc.hpp" -#include "opencv2/photo.hpp" - #ifdef GTEST_CREATE_SHARED_LIBRARY #error no modules except ts should have GTEST_CREATE_SHARED_LIBRARY defined #endif diff --git a/modules/gpuimgproc/src/bilateral_filter.cpp b/modules/gpuimgproc/src/bilateral_filter.cpp new file mode 100644 index 0000000..0c14987 --- /dev/null +++ b/modules/gpuimgproc/src/bilateral_filter.cpp @@ -0,0 +1,99 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2009, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "precomp.hpp" + +using namespace cv; +using namespace cv::gpu; + +#if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) + +void cv::gpu::bilateralFilter(const GpuMat&, GpuMat&, int, float, float, int, Stream&) { throw_no_cuda(); } + +#else + +namespace cv { namespace gpu { namespace cudev +{ + namespace imgproc + { + template + void bilateral_filter_gpu(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t stream); + } +}}} + +void cv::gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& s) +{ + using cv::gpu::cudev::imgproc::bilateral_filter_gpu; + + typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t s); + + static const func_t funcs[6][4] = + { + {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu }, + {0 /*bilateral_filter_gpu*/, 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/, 0 /*bilateral_filter_gpu*/}, + {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/, bilateral_filter_gpu , bilateral_filter_gpu }, + {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu }, + {0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ }, + {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu } + }; + + sigma_color = (sigma_color <= 0 ) ? 1 : sigma_color; + sigma_spatial = (sigma_spatial <= 0 ) ? 1 : sigma_spatial; + + + int radius = (kernel_size <= 0) ? cvRound(sigma_spatial*1.5) : kernel_size/2; + kernel_size = std::max(radius, 1)*2 + 1; + + CV_Assert(src.depth() <= CV_32F && src.channels() <= 4); + const func_t func = funcs[src.depth()][src.channels() - 1]; + CV_Assert(func != 0); + + CV_Assert(borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP); + + int gpuBorderType; + CV_Assert(tryConvertToGpuBorderType(borderMode, gpuBorderType)); + + dst.create(src.size(), src.type()); + func(src, dst, kernel_size, sigma_spatial, sigma_color, gpuBorderType, StreamAccessor::getStream(s)); +} + +#endif diff --git a/modules/gpuimgproc/test/test_imgproc.cpp b/modules/gpuimgproc/test/test_imgproc.cpp index 0e66fe0..0fa1d0f 100644 --- a/modules/gpuimgproc/test/test_imgproc.cpp +++ b/modules/gpuimgproc/test/test_imgproc.cpp @@ -881,7 +881,7 @@ GPU_TEST_P(BilateralFilter, Accuracy) EXPECT_MAT_NEAR(dst_gold, dst, src.depth() == CV_32F ? 1e-3 : 1.0); } -INSTANTIATE_TEST_CASE_P(GPU_Denoising, BilateralFilter, testing::Combine( +INSTANTIATE_TEST_CASE_P(GPU_ImgProc, BilateralFilter, testing::Combine( ALL_DEVICES, testing::Values(cv::Size(128, 128), cv::Size(113, 113), cv::Size(639, 481)), testing::Values(MatType(CV_8UC1), MatType(CV_8UC3), MatType(CV_32FC1), MatType(CV_32FC3)) diff --git a/modules/photo/CMakeLists.txt b/modules/photo/CMakeLists.txt index 08a72ea..d366512 100644 --- a/modules/photo/CMakeLists.txt +++ b/modules/photo/CMakeLists.txt @@ -1,2 +1,2 @@ set(the_description "Computational Photography") -ocv_define_module(photo opencv_imgproc) +ocv_define_module(photo opencv_imgproc OPTIONAL opencv_gpuimgproc) diff --git a/modules/photo/doc/denoising.rst b/modules/photo/doc/denoising.rst index 97625d3..5a4d744 100644 --- a/modules/photo/doc/denoising.rst +++ b/modules/photo/doc/denoising.rst @@ -89,3 +89,102 @@ Modification of ``fastNlMeansDenoisingMulti`` function for colored images sequen The function converts images to CIELAB colorspace and then separately denoise L and AB components with given h parameters using ``fastNlMeansDenoisingMulti`` function. + + +gpu::nonLocalMeans +------------------- +Performs pure non local means denoising without any simplification, and thus it is not fast. + +.. ocv:function:: void gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()) + + :param src: Source image. Supports only CV_8UC1, CV_8UC2 and CV_8UC3. + + :param dst: Destination image. + + :param h: Filter sigma regulating filter strength for color. + + :param search_window: Size of search window. + + :param block_size: Size of block used for computing weights. + + :param borderMode: Border type. See :ocv:func:`borderInterpolate` for details. ``BORDER_REFLECT101`` , ``BORDER_REPLICATE`` , ``BORDER_CONSTANT`` , ``BORDER_REFLECT`` and ``BORDER_WRAP`` are supported for now. + + :param stream: Stream for the asynchronous version. + +.. seealso:: + + :ocv:func:`fastNlMeansDenoising` + + + +gpu::FastNonLocalMeansDenoising +------------------------------- +.. ocv:class:: gpu::FastNonLocalMeansDenoising + + :: + + class FastNonLocalMeansDenoising + { + public: + //! Simple method, recommended for grayscale images (though it supports multichannel images) + void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) + //! Processes luminance and color components separatelly + void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) + }; + +The class implements fast approximate Non Local Means Denoising algorithm. + + + +gpu::FastNonLocalMeansDenoising::simpleMethod() +----------------------------------------------- +Perform image denoising using Non-local Means Denoising algorithm http://www.ipol.im/pub/algo/bcm_non_local_means_denoising with several computational optimizations. Noise expected to be a gaussian white noise + +.. ocv:function:: void gpu::FastNonLocalMeansDenoising::simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) + + :param src: Input 8-bit 1-channel, 2-channel or 3-channel image. + + :param dst: Output image with the same size and type as ``src`` . + + :param h: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise + + :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels + + :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels + + :param stream: Stream for the asynchronous invocations. + +This function expected to be applied to grayscale images. For colored images look at ``FastNonLocalMeansDenoising::labMethod``. + +.. seealso:: + + :ocv:func:`fastNlMeansDenoising` + + + +gpu::FastNonLocalMeansDenoising::labMethod() +-------------------------------------------- +Modification of ``FastNonLocalMeansDenoising::simpleMethod`` for color images + +.. ocv:function:: void gpu::FastNonLocalMeansDenoising::labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()) + + :param src: Input 8-bit 3-channel image. + + :param dst: Output image with the same size and type as ``src`` . + + :param h_luminance: Parameter regulating filter strength. Big h value perfectly removes noise but also removes image details, smaller h value preserves details but also preserves some noise + + :param float: The same as h but for color components. For most images value equals 10 will be enought to remove colored noise and do not distort colors + + :param search_window: Size in pixels of the window that is used to compute weighted average for given pixel. Should be odd. Affect performance linearly: greater search_window - greater denoising time. Recommended value 21 pixels + + :param block_size: Size in pixels of the template patch that is used to compute weights. Should be odd. Recommended value 7 pixels + + :param stream: Stream for the asynchronous invocations. + +The function converts image to CIELAB colorspace and then separately denoise L and AB components with given h parameters using ``FastNonLocalMeansDenoising::simpleMethod`` function. + +.. seealso:: + + :ocv:func:`fastNlMeansDenoisingColored` + diff --git a/modules/photo/include/opencv2/photo/gpu.hpp b/modules/photo/include/opencv2/photo/gpu.hpp new file mode 100644 index 0000000..8a018b5 --- /dev/null +++ b/modules/photo/include/opencv2/photo/gpu.hpp @@ -0,0 +1,71 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000-2008, Intel Corporation, all rights reserved. +// Copyright (C) 2008-2012, Willow Garage Inc., all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of the copyright holders may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#ifndef __OPENCV_PHOTO_GPU_HPP__ +#define __OPENCV_PHOTO_GPU_HPP__ + +#include "opencv2/core/gpumat.hpp" + +namespace cv { namespace gpu { + +//! Brute force non-local means algorith (slow but universal) +CV_EXPORTS void nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, int borderMode = BORDER_DEFAULT, Stream& s = Stream::Null()); + +//! Fast (but approximate)version of non-local means algorith similar to CPU function (running sums technique) +class CV_EXPORTS FastNonLocalMeansDenoising +{ +public: + //! Simple method, recommended for grayscale images (though it supports multichannel images) + void simpleMethod(const GpuMat& src, GpuMat& dst, float h, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); + + //! Processes luminance and color components separatelly + void labMethod(const GpuMat& src, GpuMat& dst, float h_luminance, float h_color, int search_window = 21, int block_size = 7, Stream& s = Stream::Null()); + +private: + + GpuMat buffer, extended_src_buffer; + GpuMat lab, l, ab; +}; + +}} // namespace cv { namespace gpu { + +#endif /* __OPENCV_PHOTO_GPU_HPP__ */ diff --git a/modules/gpuimgproc/perf/perf_denoising.cpp b/modules/photo/perf/perf_gpu.cpp similarity index 82% rename from modules/gpuimgproc/perf/perf_denoising.cpp rename to modules/photo/perf/perf_gpu.cpp index 1e33601..f33dd81 100644 --- a/modules/gpuimgproc/perf/perf_denoising.cpp +++ b/modules/photo/perf/perf_gpu.cpp @@ -42,6 +42,9 @@ #include "perf_precomp.hpp" +#include "opencv2/photo/gpu.hpp" +#include "opencv2/ts/gpu_perf.hpp" + using namespace std; using namespace testing; using namespace perf; @@ -49,52 +52,6 @@ using namespace perf; #define GPU_DENOISING_IMAGE_SIZES testing::Values(perf::szVGA, perf::sz720p) ////////////////////////////////////////////////////////////////////// -// BilateralFilter - -DEF_PARAM_TEST(Sz_Depth_Cn_KernelSz, cv::Size, MatDepth, MatCn, int); - -PERF_TEST_P(Sz_Depth_Cn_KernelSz, Denoising_BilateralFilter, - Combine(GPU_DENOISING_IMAGE_SIZES, - Values(CV_8U, CV_32F), - GPU_CHANNELS_1_3, - Values(3, 5, 9))) -{ - declare.time(60.0); - - const cv::Size size = GET_PARAM(0); - const int depth = GET_PARAM(1); - const int channels = GET_PARAM(2); - const int kernel_size = GET_PARAM(3); - - const float sigma_color = 7; - const float sigma_spatial = 5; - const int borderMode = cv::BORDER_REFLECT101; - - const int type = CV_MAKE_TYPE(depth, channels); - - cv::Mat src(size, type); - declare.in(src, WARMUP_RNG); - - if (PERF_RUN_GPU()) - { - const cv::gpu::GpuMat d_src(src); - cv::gpu::GpuMat dst; - - TEST_CYCLE() cv::gpu::bilateralFilter(d_src, dst, kernel_size, sigma_color, sigma_spatial, borderMode); - - GPU_SANITY_CHECK(dst); - } - else - { - cv::Mat dst; - - TEST_CYCLE() cv::bilateralFilter(src, dst, kernel_size, sigma_color, sigma_spatial, borderMode); - - CPU_SANITY_CHECK(dst); - } -} - -////////////////////////////////////////////////////////////////////// // nonLocalMeans DEF_PARAM_TEST(Sz_Depth_Cn_WinSz_BlockSz, cv::Size, MatDepth, MatCn, int, int); diff --git a/modules/gpuimgproc/src/cuda/nlm.cu b/modules/photo/src/cuda/nlm.cu similarity index 100% rename from modules/gpuimgproc/src/cuda/nlm.cu rename to modules/photo/src/cuda/nlm.cu diff --git a/modules/gpuimgproc/src/denoising.cpp b/modules/photo/src/denoising_gpu.cpp similarity index 72% rename from modules/gpuimgproc/src/denoising.cpp rename to modules/photo/src/denoising_gpu.cpp index 1687f8e..2164731 100644 --- a/modules/gpuimgproc/src/denoising.cpp +++ b/modules/photo/src/denoising_gpu.cpp @@ -42,18 +42,20 @@ #include "precomp.hpp" +#include "opencv2/photo/gpu.hpp" +#include "opencv2/core/gpu_private.hpp" +#include "opencv2/gpuarithm.hpp" +#include "opencv2/gpuimgproc.hpp" + using namespace cv; using namespace cv::gpu; #if !defined (HAVE_CUDA) || defined (CUDA_DISABLER) -void cv::gpu::bilateralFilter(const GpuMat&, GpuMat&, int, float, float, int, Stream&) { throw_no_cuda(); } void cv::gpu::nonLocalMeans(const GpuMat&, GpuMat&, float, int, int, int, Stream&) { throw_no_cuda(); } - void cv::gpu::FastNonLocalMeansDenoising::simpleMethod(const GpuMat&, GpuMat&, float, int, int, Stream&) { throw_no_cuda(); } void cv::gpu::FastNonLocalMeansDenoising::labMethod( const GpuMat&, GpuMat&, float, float, int, int, Stream&) { throw_no_cuda(); } - #else ////////////////////////////////////////////////////////////////////////////////// @@ -64,49 +66,10 @@ namespace cv { namespace gpu { namespace cudev namespace imgproc { template - void bilateral_filter_gpu(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t stream); - - template void nlm_bruteforce_gpu(const PtrStepSzb& src, PtrStepSzb dst, int search_radius, int block_radius, float h, int borderMode, cudaStream_t stream); } }}} -void cv::gpu::bilateralFilter(const GpuMat& src, GpuMat& dst, int kernel_size, float sigma_color, float sigma_spatial, int borderMode, Stream& s) -{ - using cv::gpu::cudev::imgproc::bilateral_filter_gpu; - - typedef void (*func_t)(const PtrStepSzb& src, PtrStepSzb dst, int kernel_size, float sigma_spatial, float sigma_color, int borderMode, cudaStream_t s); - - static const func_t funcs[6][4] = - { - {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu }, - {0 /*bilateral_filter_gpu*/, 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/, 0 /*bilateral_filter_gpu*/}, - {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/, bilateral_filter_gpu , bilateral_filter_gpu }, - {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu }, - {0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ , 0 /*bilateral_filter_gpu*/ }, - {bilateral_filter_gpu , 0 /*bilateral_filter_gpu*/ , bilateral_filter_gpu , bilateral_filter_gpu } - }; - - sigma_color = (sigma_color <= 0 ) ? 1 : sigma_color; - sigma_spatial = (sigma_spatial <= 0 ) ? 1 : sigma_spatial; - - - int radius = (kernel_size <= 0) ? cvRound(sigma_spatial*1.5) : kernel_size/2; - kernel_size = std::max(radius, 1)*2 + 1; - - CV_Assert(src.depth() <= CV_32F && src.channels() <= 4); - const func_t func = funcs[src.depth()][src.channels() - 1]; - CV_Assert(func != 0); - - CV_Assert(borderMode == BORDER_REFLECT101 || borderMode == BORDER_REPLICATE || borderMode == BORDER_CONSTANT || borderMode == BORDER_REFLECT || borderMode == BORDER_WRAP); - - int gpuBorderType; - CV_Assert(tryConvertToGpuBorderType(borderMode, gpuBorderType)); - - dst.create(src.size(), src.type()); - func(src, dst, kernel_size, sigma_spatial, sigma_color, gpuBorderType, StreamAccessor::getStream(s)); -} - void cv::gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_window, int block_window, int borderMode, Stream& s) { using cv::gpu::cudev::imgproc::nlm_bruteforce_gpu; @@ -129,11 +92,6 @@ void cv::gpu::nonLocalMeans(const GpuMat& src, GpuMat& dst, float h, int search_ func(src, dst, search_window/2, block_window/2, h, gpuBorderType, StreamAccessor::getStream(s)); } - -////////////////////////////////////////////////////////////////////////////////// -//// Non Local Means Denosing (fast approxinate) - - namespace cv { namespace gpu { namespace cudev { namespace imgproc diff --git a/modules/gpuimgproc/test/test_denoising.cpp b/modules/photo/test/test_denoising_gpu.cpp similarity index 85% rename from modules/gpuimgproc/test/test_denoising.cpp rename to modules/photo/test/test_denoising_gpu.cpp index cb4ea1e..f46a49f 100644 --- a/modules/gpuimgproc/test/test_denoising.cpp +++ b/modules/photo/test/test_denoising_gpu.cpp @@ -42,26 +42,17 @@ #include "test_precomp.hpp" +#include "opencv2/photo/gpu.hpp" +#include "opencv2/ts/gpu_test.hpp" + #ifdef HAVE_CUDA using namespace cvtest; - //////////////////////////////////////////////////////// // Brute Force Non local means -struct BruteForceNonLocalMeans: testing::TestWithParam -{ - cv::gpu::DeviceInfo devInfo; - - virtual void SetUp() - { - devInfo = GetParam(); - cv::gpu::setDevice(devInfo.deviceID()); - } -}; - -GPU_TEST_P(BruteForceNonLocalMeans, Regression) +TEST(BruteForceNonLocalMeans, Regression) { using cv::gpu::GpuMat; @@ -88,23 +79,10 @@ GPU_TEST_P(BruteForceNonLocalMeans, Regression) EXPECT_MAT_NEAR(gray_gold, dgray, 1e-4); } -INSTANTIATE_TEST_CASE_P(GPU_Denoising, BruteForceNonLocalMeans, ALL_DEVICES); - //////////////////////////////////////////////////////// // Fast Force Non local means -struct FastNonLocalMeans: testing::TestWithParam -{ - cv::gpu::DeviceInfo devInfo; - - virtual void SetUp() - { - devInfo = GetParam(); - cv::gpu::setDevice(devInfo.deviceID()); - } -}; - -GPU_TEST_P(FastNonLocalMeans, Regression) +TEST(FastNonLocalMeans, Regression) { using cv::gpu::GpuMat; @@ -133,6 +111,4 @@ GPU_TEST_P(FastNonLocalMeans, Regression) EXPECT_MAT_NEAR(gray_gold, dgray, 1); } -INSTANTIATE_TEST_CASE_P(GPU_Denoising, FastNonLocalMeans, ALL_DEVICES); - #endif // HAVE_CUDA -- 2.7.4