From 48f132f35f27a4dd189ebca660ed438338c6c01e Mon Sep 17 00:00:00 2001 From: Vitaly Tuzov Date: Wed, 7 Sep 2016 18:30:17 +0300 Subject: [PATCH] Fix Sobel evaluation for image ROI without isolated border. --- modules/imgproc/src/canny.cpp | 3 ++ modules/imgproc/src/deriv.cpp | 6 ++- modules/imgproc/test/ocl/test_canny.cpp | 12 +----- modules/imgproc/test/test_filter.cpp | 50 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 784b5ffe24..22ec1f39c8 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -69,6 +69,9 @@ static bool ippCanny(const Mat& _src, const Mat& dx_, const Mat& dy_, Mat& _dst, CV_INSTRUMENT_REGION_IPP() #if USE_IPP_CANNY + if (!useCustomDeriv && _src.isSubmatrix()) + return false; // IPP Sobel doesn't support transparent ROI border + int size = 0, size1 = 0; IppiSize roi = { _src.cols, _src.rows }; diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index aa9183aceb..0dce2fd9e7 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -307,7 +307,7 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, { CV_INSTRUMENT_REGION_IPP() - if ((borderType != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) + if (((borderType & ~BORDER_ISOLATED) != BORDER_REPLICATE) || ((3 != ksize) && (5 != ksize))) return false; if (fabs(delta) > FLT_EPSILON) return false; @@ -317,6 +317,10 @@ static bool IPPDerivSobel(InputArray _src, OutputArray _dst, int ddepth, int dx, int bufSize = 0; cv::AutoBuffer buffer; Mat src = _src.getMat(), dst = _dst.getMat(); + + if ((borderType & BORDER_ISOLATED) == 0 && src.isSubmatrix()) + return false; + if ( ddepth < 0 ) ddepth = src.depth(); diff --git a/modules/imgproc/test/ocl/test_canny.cpp b/modules/imgproc/test/ocl/test_canny.cpp index f9c724b049..ca436a4f67 100644 --- a/modules/imgproc/test/ocl/test_canny.cpp +++ b/modules/imgproc/test/ocl/test_canny.cpp @@ -99,11 +99,7 @@ OCL_TEST_P(Canny, Accuracy) generateTestData(); const double low_thresh = 50.0, high_thresh = 100.0; - double eps = 1e-2; -#ifdef ANDROID - if (cv::ocl::Device::getDefault().isNVidia()) - eps = 12e-3; -#endif + double eps = 12e-3; OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); OCL_ON(cv::Canny(usrc_roi, udst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); @@ -117,11 +113,7 @@ OCL_TEST_P(Canny, AccuracyCustomGradient) generateTestData(); const double low_thresh = 50.0, high_thresh = 100.0; - double eps = 1e-2; -#ifdef ANDROID - if (cv::ocl::Device::getDefault().isNVidia()) - eps = 12e-3; -#endif + double eps = 12e-3; OCL_OFF(cv::Canny(src_roi, dst_roi, low_thresh, high_thresh, aperture_size, useL2gradient)); OCL_ON( diff --git a/modules/imgproc/test/test_filter.cpp b/modules/imgproc/test/test_filter.cpp index 5994b1b11b..886c5ab90a 100644 --- a/modules/imgproc/test/test_filter.cpp +++ b/modules/imgproc/test/test_filter.cpp @@ -2015,3 +2015,53 @@ TEST(Imgproc_Morphology, iterated) ASSERT_EQ(0.0, norm(dst0, dst2, NORM_INF)); } } + +TEST(Imgproc_Sobel, borderTypes) +{ + int kernelSize = 3; + + /// ksize > src_roi.size() + Mat src = (Mat_(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9), dst, expected_dst; + Mat src_roi = src(Rect(1, 1, 1, 1)); + src_roi.setTo(cv::Scalar::all(0)); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE); + EXPECT_EQ(8, dst.at(0, 0)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT); + EXPECT_EQ(8, dst.at(0, 0)); + + // should work like BORDER_ISOLATED + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE | BORDER_ISOLATED); + EXPECT_EQ(0, dst.at(0, 0)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT | BORDER_ISOLATED); + EXPECT_EQ(0, dst.at(0, 0)); + + /// ksize <= src_roi.size() + src = Mat(5, 5, CV_8UC1, cv::Scalar(5)); + src_roi = src(Rect(1, 1, 3, 3)); + src_roi.setTo(0); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + expected_dst = + (Mat_(3, 3) << -15, 0, 15, -20, 0, 20, -15, 0, 15); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + + // should work like !BORDER_ISOLATED, so the function MUST read values in full matrix + expected_dst = Mat::zeros(3, 3, CV_16SC1); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REPLICATE | BORDER_ISOLATED); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); + Sobel(src_roi, dst, CV_16S, 1, 0, kernelSize, 1, 0, BORDER_REFLECT | BORDER_ISOLATED); + EXPECT_EQ(expected_dst.type(), dst.type()); + EXPECT_EQ(expected_dst.size(), dst.size()); + EXPECT_DOUBLE_EQ(0.0, cvtest::norm(expected_dst, dst, NORM_INF)); +}