diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index eca0db3fde..bc11b24635 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -413,15 +413,15 @@ static bool IPPDeriv(const Mat& src, Mat& dst, int ddepth, int dx, int dy, int k void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) { + Mat src = _src.getMat(), dst = _dst.getMat(); if (ksize == 3 && tegra::sobel3x3(src, dst, dx, dy, borderType)) return; if (ksize == -1 && tegra::scharr(src, dst, dx, dy, borderType)) @@ -430,13 +430,14 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, #endif #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) - if(dx < 3 && dy < 3 && src.channels() == 1 && borderType == 1) + if(dx < 3 && dy < 3 && cn == 1 && borderType == BORDER_REPLICATE) { + Mat src = _src.getMat(), dst = _dst.getMat(); if(IPPDeriv(src, dst, ddepth, dx, dy, ksize,scale)) return; } #endif - int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); + int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; getDerivKernels( kx, ky, dx, dy, ksize, false, ktype ); @@ -449,33 +450,36 @@ void cv::Sobel( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, else ky *= scale; } - sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType ); + sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); } void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) + { + Mat src = _src.getMat(), dst = _dst.getMat(); if (tegra::scharr(src, dst, dx, dy, borderType)) return; + } #endif #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7) if(dx < 2 && dy < 2 && src.channels() == 1 && borderType == 1) { + Mat src = _src.getMat(), dst = _dst.getMat(); if(IPPDerivScharr(src, dst, ddepth, dx, dy, scale)) return; } #endif - int ktype = std::max(CV_32F, std::max(ddepth, src.depth())); + int ktype = std::max(CV_32F, std::max(ddepth, sdepth)); Mat kx, ky; getScharrKernels( kx, ky, dx, dy, false, ktype ); @@ -488,22 +492,22 @@ void cv::Scharr( InputArray _src, OutputArray _dst, int ddepth, int dx, int dy, else ky *= scale; } - sepFilter2D( src, dst, ddepth, kx, ky, Point(-1,-1), delta, borderType ); + sepFilter2D( _src, _dst, ddepth, kx, ky, Point(-1, -1), delta, borderType ); } void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, double scale, double delta, int borderType ) { - Mat src = _src.getMat(); + int stype = _src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype); if (ddepth < 0) - ddepth = src.depth(); - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); + ddepth = sdepth; + _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) ); #ifdef HAVE_TEGRA_OPTIMIZATION if (scale == 1.0 && delta == 0) { + Mat src = _src.getMat(), dst = _dst.getMat(); if (ksize == 1 && tegra::laplace1(src, dst, borderType)) return; if (ksize == 3 && tegra::laplace3(src, dst, borderType)) @@ -516,15 +520,18 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, if( ksize == 1 || ksize == 3 ) { float K[2][9] = - {{0, 1, 0, 1, -4, 1, 0, 1, 0}, - {2, 0, 2, 0, -8, 0, 2, 0, 2}}; + { + { 0, 1, 0, 1, -4, 1, 0, 1, 0 }, + { 2, 0, 2, 0, -8, 0, 2, 0, 2 } + }; Mat kernel(3, 3, CV_32F, K[ksize == 3]); if( scale != 1 ) kernel *= scale; - filter2D( src, dst, ddepth, kernel, Point(-1,-1), delta, borderType ); + filter2D( _src, _dst, ddepth, kernel, Point(-1, -1), delta, borderType ); } else { + Mat src = _src.getMat(), dst = _dst.getMat(); const size_t STRIPE_SIZE = 1 << 14; int depth = src.depth(); diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 7ef850863f..9d280c9878 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -798,10 +798,10 @@ cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype ) return kernel; } +namespace cv { -cv::Ptr cv::createGaussianFilter( int type, Size ksize, - double sigma1, double sigma2, - int borderType ) +static void createGaussianKernels( Mat & kx, Mat & ky, int type, Size ksize, + double sigma1, double sigma2 ) { int depth = CV_MAT_DEPTH(type); if( sigma2 <= 0 ) @@ -819,12 +819,21 @@ cv::Ptr cv::createGaussianFilter( int type, Size ksize, sigma1 = std::max( sigma1, 0. ); sigma2 = std::max( sigma2, 0. ); - Mat kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) ); - Mat ky; + kx = getGaussianKernel( ksize.width, sigma1, std::max(depth, CV_32F) ); if( ksize.height == ksize.width && std::abs(sigma1 - sigma2) < DBL_EPSILON ) ky = kx; else ky = getGaussianKernel( ksize.height, sigma2, std::max(depth, CV_32F) ); +} + +} + +cv::Ptr cv::createGaussianFilter( int type, Size ksize, + double sigma1, double sigma2, + int borderType ) +{ + Mat kx, ky; + createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); return createSeparableLinearFilter( type, type, kx, ky, Point(-1,-1), 0, borderType ); } @@ -834,33 +843,34 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { - Mat src = _src.getMat(); - _dst.create( src.size(), src.type() ); - Mat dst = _dst.getMat(); + int type = _src.type(); + Size size = _src.size(); + _dst.create( size, type ); if( borderType != BORDER_CONSTANT ) { - if( src.rows == 1 ) + if( size.height == 1 ) ksize.height = 1; - if( src.cols == 1 ) + if( size.width == 1 ) ksize.width = 1; } if( ksize.width == 1 && ksize.height == 1 ) { - src.copyTo(dst); + _src.copyTo(_dst); return; } #ifdef HAVE_TEGRA_OPTIMIZATION - if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(src, dst, ksize, borderType)) + if(sigma1 == 0 && sigma2 == 0 && tegra::gaussian(_src.getMat(), _dst.getMat(), ksize, borderType)) return; #endif #if defined HAVE_IPP && (IPP_VERSION_MAJOR >= 7) - if(src.type() == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 ) + if( type == CV_32FC1 && sigma1 == sigma2 && ksize.width == ksize.height && sigma1 != 0.0 ) { - IppiSize roi = {src.cols, src.rows}; + Mat src = _src.getMat(), dst = _dst.getMat(); + IppiSize roi = { src.cols, src.rows }; int bufSize = 0; ippiFilterGaussGetBufferSize_32f_C1R(roi, ksize.width, &bufSize); AutoBuffer buf(bufSize+128); @@ -873,11 +883,11 @@ void cv::GaussianBlur( InputArray _src, OutputArray _dst, Size ksize, } #endif - Ptr f = createGaussianFilter( src.type(), ksize, sigma1, sigma2, borderType ); - f->apply( src, dst ); + Mat kx, ky; + createGaussianKernels(kx, ky, type, ksize, sigma1, sigma2); + sepFilter2D(_src, _dst, CV_MAT_DEPTH(type), kx, ky, Point(-1,-1), 0, borderType ); } - /****************************************************************************************\ Median Filter \****************************************************************************************/ diff --git a/modules/imgproc/test/ocl/test_filters.cpp b/modules/imgproc/test/ocl/test_filters.cpp index 58d23e8358..5953d80701 100644 --- a/modules/imgproc/test/ocl/test_filters.cpp +++ b/modules/imgproc/test/ocl/test_filters.cpp @@ -60,7 +60,7 @@ namespace ocl { PARAM_TEST_CASE(FilterTestBase, MatType, int, // kernel size Size, // dx, dy - int, // border type + BorderType, // border type double, // optional parameter bool) // roi or not { @@ -145,32 +145,146 @@ OCL_TEST_P(Bilateral, Mat) } } +///////////////////////////////////////////////////////////////////////////////////////////////// +// Laplacian + +typedef FilterTestBase LaplacianTest; + +OCL_TEST_P(LaplacianTest, Accuracy) +{ + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Laplacian(src_roi, dst_roi, -1, ksize, scale, 0, borderType)); + OCL_ON(cv::Laplacian(usrc_roi, udst_roi, -1, ksize, scale, 0, borderType)); + + Near(); + } +} + + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Sobel + +typedef FilterTestBase SobelTest; + +OCL_TEST_P(SobelTest, Mat) +{ + int dx = size.width, dy = size.height; + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Sobel(src_roi, dst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType)); + OCL_ON(cv::Sobel(usrc_roi, udst_roi, -1, dx, dy, ksize, scale, /* delta */0, borderType)); + + Near(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// Scharr + +typedef FilterTestBase ScharrTest; + +OCL_TEST_P(ScharrTest, Mat) +{ + int dx = size.width, dy = size.height; + double scale = param; + + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + OCL_OFF(cv::Scharr(src_roi, dst_roi, -1, dx, dy, scale, /* delta */ 0, borderType)); + OCL_ON(cv::Scharr(usrc_roi, udst_roi, -1, dx, dy, scale, /* delta */ 0, borderType)); + + Near(); + } +} + +///////////////////////////////////////////////////////////////////////////////////////////////// +// GaussianBlur + +typedef FilterTestBase GaussianBlurTest; + +OCL_TEST_P(GaussianBlurTest, Mat) +{ + for (int j = 0; j < test_loop_times; j++) + { + random_roi(); + + double sigma1 = rng.uniform(0.1, 1.0); + double sigma2 = rng.uniform(0.1, 1.0); + + OCL_OFF(cv::GaussianBlur(src_roi, dst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); + OCL_ON(cv::GaussianBlur(usrc_roi, udst_roi, Size(ksize, ksize), sigma1, sigma2, borderType)); + + Near(CV_MAT_DEPTH(type) == CV_8U ? 3 : 5e-5, false); + } +} + ////////////////////////////////////////////////////////////////////////////////////////////////////////////// #define FILTER_BORDER_SET_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, (int)BORDER_WRAP, (int)BORDER_REFLECT_101/*, \ + Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, (BorderType)BORDER_WRAP, (BorderType)BORDER_REFLECT_101/*, \ (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version #define FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED \ - Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (int)BORDER_REFLECT_101/*, \ + Values((BorderType)BORDER_CONSTANT, (BorderType)BORDER_REPLICATE, (BorderType)BORDER_REFLECT, /*(int)BORDER_WRAP,*/ (BorderType)BORDER_REFLECT_101/*, \ (int)BORDER_CONSTANT|BORDER_ISOLATED, (int)BORDER_REPLICATE|BORDER_ISOLATED, \ (int)BORDER_REFLECT|BORDER_ISOLATED, (int)BORDER_WRAP|BORDER_ISOLATED, \ (int)BORDER_REFLECT_101|BORDER_ISOLATED*/) // WRAP and ISOLATED are not supported by cv:: version -#define FILTER_DATATYPES Values(CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4, \ - CV_32FC1, CV_32FC3, CV_32FC4, \ - CV_64FC1, CV_64FC3, CV_64FC4) +#define FILTER_TYPES Values(CV_8UC1, CV_8UC2, CV_8UC4, CV_32FC1, CV_32FC4, CV_64FC1, CV_64FC4) OCL_INSTANTIATE_TEST_CASE_P(Filter, Bilateral, Combine( Values((MatType)CV_8UC1), - Values(5, 9), + Values(5, 9), // kernel size Values(Size(0, 0)), // not used FILTER_BORDER_SET_NO_ISOLATED, Values(0.0), // not used Bool())); +OCL_INSTANTIATE_TEST_CASE_P(Filter, LaplacianTest, Combine( + FILTER_TYPES, + Values(1, 3), // kernel size + Values(Size(0, 0)), // not used + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(1.0, 0.2, 3.0), // kernel scale + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, SobelTest, Combine( + FILTER_TYPES, + Values(3, 5), // kernel size + Values(Size(1, 0), Size(1, 1), Size(2, 0), Size(2, 1)), // dx, dy + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(0.0), // not used + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, ScharrTest, Combine( + FILTER_TYPES, + Values(0), // not used + Values(Size(0, 1), Size(1, 0)), // dx, dy + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(1.0, 0.2), // kernel scale + Bool())); + +OCL_INSTANTIATE_TEST_CASE_P(Filter, GaussianBlurTest, Combine( + FILTER_TYPES, + Values(3, 5), // kernel size + Values(Size(0, 0)), // not used + FILTER_BORDER_SET_NO_WRAP_NO_ISOLATED, + Values(0.0), // not used + Bool())); + } } // namespace cvtest::ocl #endif // HAVE_OPENCL diff --git a/modules/ts/include/opencv2/ts/ocl_test.hpp b/modules/ts/include/opencv2/ts/ocl_test.hpp index 1b66799ed0..a9604612c1 100644 --- a/modules/ts/include/opencv2/ts/ocl_test.hpp +++ b/modules/ts/include/opencv2/ts/ocl_test.hpp @@ -307,7 +307,7 @@ IMPLEMENT_PARAM_CLASS(Channels, int) CV_ENUM(Interpolation, INTER_NEAREST, INTER_LINEAR, INTER_CUBIC, INTER_AREA) CV_ENUM(ThreshOp, THRESH_BINARY, THRESH_BINARY_INV, THRESH_TRUNC, THRESH_TOZERO, THRESH_TOZERO_INV) -CV_ENUM(BorderType, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) +CV_ENUM(BorderType, BORDER_CONSTANT, BORDER_REPLICATE, BORDER_REFLECT, BORDER_WRAP, BORDER_REFLECT_101) #define OCL_INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ INSTANTIATE_TEST_CASE_P(OCL_ ## prefix, test_case_name, generator)