diff --git a/modules/imgproc/perf/perf_blur.cpp b/modules/imgproc/perf/perf_blur.cpp index 2a284dc5b9..956782e38c 100644 --- a/modules/imgproc/perf/perf_blur.cpp +++ b/modules/imgproc/perf/perf_blur.cpp @@ -43,6 +43,9 @@ typedef perf::TestBaseWithParam Size_MatType_Borde typedef std::tr1::tuple Size_MatType_BorderType_t; typedef perf::TestBaseWithParam Size_MatType_BorderType; +typedef std::tr1::tuple Size_ksize_BorderType_t; +typedef perf::TestBaseWithParam Size_ksize_BorderType; + PERF_TEST_P(Size_MatType_BorderType3x3, gaussianBlur3x3, testing::Combine( testing::Values(szODD, szQVGA, szVGA, sz720p), @@ -134,6 +137,28 @@ PERF_TEST_P(Size_MatType_BorderType3x3, box3x3, SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); } +PERF_TEST_P(Size_ksize_BorderType, box_CV8U_CV16U, + testing::Combine( + testing::Values(szODD, szQVGA, szVGA, sz720p), + testing::Values(3, 5, 15), + BorderType3x3::all() + ) + ) +{ + Size size = get<0>(GetParam()); + int ksize = get<1>(GetParam()); + BorderType3x3 btype = get<2>(GetParam()); + + Mat src(size, CV_8UC1); + Mat dst(size, CV_16UC1); + + declare.in(src, WARMUP_RNG).out(dst); + + TEST_CYCLE() boxFilter(src, dst, CV_16UC1, Size(ksize, ksize), Point(-1,-1), false, btype); + + SANITY_CHECK(dst, 1e-6, ERROR_RELATIVE); +} + PERF_TEST_P(Size_MatType_BorderType3x3, box3x3_inplace, testing::Combine( testing::Values(szODD, szQVGA, szVGA, sz720p), diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index e732ce5077..1302407a25 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4333,7 +4333,7 @@ static bool ocl_sepFilter2D_SinglePass(InputArray _src, OutputArray _dst, return k.run(2, gt2, lt2, false); } -static bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, +bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, double delta, int borderType ) { diff --git a/modules/imgproc/src/filter.hpp b/modules/imgproc/src/filter.hpp index c878fea281..93f3f177e6 100644 --- a/modules/imgproc/src/filter.hpp +++ b/modules/imgproc/src/filter.hpp @@ -50,6 +50,12 @@ namespace cv int SymmColumnVec_32f_Symm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2); int SymmColumnVec_32f_Unsymm_AVX(const float** src, const float* ky, float* dst, float delta, int width, int ksize2); #endif + +#ifdef HAVE_OPENCL + bool ocl_sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, + InputArray _kernelX, InputArray _kernelY, Point anchor, + double delta, int borderType ); +#endif } #endif diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index be05644067..d48090506f 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -664,6 +664,43 @@ inline int hal_ni_threshold(const uchar* src_data, size_t src_step, uchar* dst_d #define cv_hal_threshold hal_ni_threshold //! @endcond +/** + @brief Calculate box filter + @param src_data,src_step Source image + @param dst_data,dst_step Destination image + @param width,height Source image dimensions + @param src_depth,dst_depth Depths of source and destination image + @param cn Number of channels + @param margin_left,margin_top,margin_right,margin_bottom Margins for source image + @param ksize_width,ksize_height Size of kernel + @param anchor_x,anchor_y Anchor point + @param normalize If true then result is normalized + @param border_type Border type +*/ +inline int hal_ni_boxFilter(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int src_depth, int dst_depth, int cn, int margin_left, int margin_top, int margin_right, int margin_bottom, size_t ksize_width, size_t ksize_height, int anchor_x, int anchor_y, bool normalize, int border_type) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_boxFilter hal_ni_boxFilter +//! @endcond + +/** + @brief Blurs an image using a Gaussian filter. + @param src_data,src_step Source image + @param dst_data,dst_step Destination image + @param width,height Source image dimensions + @param depth Depth of source and destination image + @param cn Number of channels + @param margin_left,margin_top,margin_right,margin_bottom Margins for source image + @param ksize_width,ksize_height Size of kernel + @param sigmaX,sigmaY Gaussian kernel standard deviation. + @param border_type Border type +*/ +inline int hal_ni_gaussianBlur(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int depth, int cn, size_t margin_left, size_t margin_top, size_t margin_right, size_t margin_bottom, size_t ksize_width, size_t ksize_height, double sigmaX, double sigmaY, int border_type) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_gaussianBlur hal_ni_gaussianBlur +//! @endcond + //! @} #if defined __GNUC__ diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 54c15e28ca..afe45af2c3 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -47,6 +47,8 @@ #include "opencv2/core/openvx/ovx_defs.hpp" +#include "filter.hpp" + /* * This file includes the code, contributed by Simon Perreault * (the function icvMedianBlur_8u_O1) @@ -1536,9 +1538,6 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, CV_OCL_RUN(_dst.isUMat(), ocl_boxFilter(_src, _dst, ddepth, ksize, anchor, borderType, normalize)) - CV_OVX_RUN(true, - openvx_boxfilter(_src, _dst, ddepth, ksize, anchor, normalize, borderType)) - Mat src = _src.getMat(); int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if( ddepth < 0 ) @@ -1552,17 +1551,21 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, if( src.cols == 1 ) ksize.width = 1; } -#ifdef HAVE_TEGRA_OPTIMIZATION - if ( tegra::useTegra() && tegra::box(src, dst, ksize, anchor, normalize, borderType) ) - return; -#endif - - CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType)); Point ofs; Size wsz(src.cols, src.rows); if(!(borderType&BORDER_ISOLATED)) src.locateROI( wsz, ofs ); + + CALL_HAL(boxFilter, cv_hal_boxFilter, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, ddepth, cn, + ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height, + anchor.x, anchor.y, normalize, borderType&~BORDER_ISOLATED); + + CV_OVX_RUN(true, + openvx_boxfilter(src, dst, ddepth, ksize, anchor, normalize, borderType)) + + CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType)); + borderType = (borderType&~BORDER_ISOLATED); Ptr f = createBoxFilter( src.type(), dst.type(), @@ -2093,29 +2096,40 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, return; } - CV_OVX_RUN(true, - openvx_gaussianBlur(_src, _dst, ksize, sigma1, sigma2, borderType)) - -#ifdef HAVE_TEGRA_OPTIMIZATION - Mat src = _src.getMat(); - Mat dst = _dst.getMat(); - if(sigma1 == 0 && sigma2 == 0 && tegra::useTegra() && tegra::gaussian(src, dst, ksize, borderType)) - return; -#endif bool useOpenCL = (ocl::isOpenCLActivated() && _dst.isUMat() && _src.dims() <= 2 && ((ksize.width == 3 && ksize.height == 3) || (ksize.width == 5 && ksize.height == 5)) && _src.rows() > ksize.height && _src.cols() > ksize.width); (void)useOpenCL; - CV_IPP_RUN(!useOpenCL, ipp_GaussianBlur( _src, _dst, ksize, sigma1, sigma2, borderType)); + int sdepth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); Mat kx, ky; createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); CV_OCL_RUN(useOpenCL, ocl_GaussianBlur_8UC1(_src, _dst, ksize, CV_MAT_DEPTH(type), kx, ky, borderType)); - sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2 && (size_t)_src.rows() > kx.total() && (size_t)_src.cols() > kx.total(), + ocl_sepFilter2D(_src, _dst, sdepth, kx, ky, Point(-1, -1), 0, borderType)) + + Mat src = _src.getMat(); + Mat dst = _dst.getMat(); + + Point ofs; + Size wsz(src.cols, src.rows); + if(!(borderType & BORDER_ISOLATED)) + src.locateROI( wsz, ofs ); + + CALL_HAL(gaussianBlur, cv_hal_gaussianBlur, src.ptr(), src.step, dst.ptr(), dst.step, src.cols, src.rows, sdepth, cn, + ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height, + sigma1, sigma2, borderType&~BORDER_ISOLATED); + + CV_OVX_RUN(true, + openvx_gaussianBlur(src, dst, ksize, sigma1, sigma2, borderType)) + + CV_IPP_RUN_FAST(ipp_GaussianBlur(src, dst, ksize, sigma1, sigma2, borderType)); + + sepFilter2D(src, dst, sdepth, kx, ky, Point(-1, -1), 0, borderType); } /****************************************************************************************\