From ab1a37d564a4b6ead065dabc8dd2c361b537638c Mon Sep 17 00:00:00 2001 From: Aaron Kunze Date: Tue, 20 May 2014 22:30:09 -0700 Subject: [PATCH] Bug fixes for filter2D and associated tests. --- modules/imgproc/perf/opencl/perf_filters.cpp | 3 +- modules/imgproc/src/filter.cpp | 37 +++++++++++++++----- modules/imgproc/test/ocl/test_filter2d.cpp | 13 ++++--- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/modules/imgproc/perf/opencl/perf_filters.cpp b/modules/imgproc/perf/opencl/perf_filters.cpp index 27dc09f1a8..9667b8f907 100644 --- a/modules/imgproc/perf/opencl/perf_filters.cpp +++ b/modules/imgproc/perf/opencl/perf_filters.cpp @@ -272,7 +272,8 @@ OCL_PERF_TEST_P(Filter2DFixture, Filter2D, checkDeviceMaxMemoryAllocSize(srcSize, type); - UMat src(srcSize, type), dst(srcSize, type), kernel(ksize, ksize, CV_32SC1); + UMat src(srcSize, type), dst(srcSize, type); + Mat kernel(ksize, ksize, CV_32SC1); declare.in(src, WARMUP_RNG).in(kernel).out(dst); randu(kernel, -3.0, 3.0); diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index d1af4065f2..9c76128881 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -3238,12 +3238,12 @@ static bool ocl_filter2D( InputArray _src, OutputArray _dst, int ddepth, if (cn <= 2 && ksize.width <= 4 && ksize.height <= 4) { pxPerWorkItemX = sz.width % 8 ? sz.width % 4 ? sz.width % 2 ? 1 : 2 : 4 : 8; - pxPerWorkItemY = sz.width % 2 ? 1 : 2; + pxPerWorkItemY = sz.height % 2 ? 1 : 2; } else if (cn < 4 || (ksize.width <= 4 && ksize.height <= 4)) { pxPerWorkItemX = sz.width % 2 ? 1 : 2; - pxPerWorkItemY = sz.width % 2 ? 1 : 2; + pxPerWorkItemY = sz.height % 2 ? 1 : 2; } globalsize[0] = sz.width / pxPerWorkItemX; globalsize[1] = sz.height / pxPerWorkItemY; @@ -3823,26 +3823,45 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, if( kernel.cols*kernel.rows >= dft_filter_size ) { Mat temp; - if( src.data != dst.data ) - temp = dst; - else - temp.create(dst.size(), dst.type()); // crossCorr doesn't accept non-zero delta with multiple channels if( src.channels() != 1 && delta != 0 ) { + // The semantics of filter2D require that the delta be applied + // as floating-point math. So wee need an intermediate Mat + // with a float datatype. If the dest is already floats, + // we just use that. + int corrDepth = dst.depth(); + if( (dst.depth() == CV_32F || dst.depth() == CV_64F) && + src.data != dst.data ) + { + temp = dst; + } + else + { + corrDepth = dst.depth() == CV_64F ? CV_64F : CV_32F; + temp.create( dst.size(), CV_MAKETYPE(corrDepth, dst.channels()) ); + } crossCorr( src, kernel, temp, src.size(), - CV_MAKETYPE(ddepth, src.channels()), + CV_MAKETYPE(corrDepth, src.channels()), anchor, 0, borderType ); add( temp, delta, temp ); + if ( temp.data != dst.data ) + { + temp.convertTo( dst, dst.type() ); + } } else { + if( src.data != dst.data ) + temp = dst; + else + temp.create(dst.size(), dst.type()); crossCorr( src, kernel, temp, src.size(), CV_MAKETYPE(ddepth, src.channels()), anchor, delta, borderType ); + if( temp.data != dst.data ) + temp.copyTo(dst); } - if( temp.data != dst.data ) - temp.copyTo(dst); return; } diff --git a/modules/imgproc/test/ocl/test_filter2d.cpp b/modules/imgproc/test/ocl/test_filter2d.cpp index 7da2718026..18ba4cc529 100644 --- a/modules/imgproc/test/ocl/test_filter2d.cpp +++ b/modules/imgproc/test/ocl/test_filter2d.cpp @@ -57,7 +57,7 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, int, int, BorderType, bool, bool) static const int kernelMaxSize = 10; int type; - Size dsize; + Size size; Point anchor; int borderType; int widthMultiple; @@ -81,17 +81,16 @@ PARAM_TEST_CASE(Filter2D, MatDepth, Channels, int, int, BorderType, bool, bool) void random_roi() { - dsize = randomSize(1, MAX_VALUE); + size = randomSize(1, MAX_VALUE); // Make sure the width is a multiple of the requested value, and no more. - dsize.width &= ~((widthMultiple * 2) - 1); - dsize.width += widthMultiple; + size.width &= ~((widthMultiple * 2) - 1); + size.width += widthMultiple; - Size roiSize = randomSize(kernel.size[0], MAX_VALUE, kernel.size[1], MAX_VALUE); Border srcBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(src, src_roi, roiSize, srcBorder, type, -MAX_VALUE, MAX_VALUE); + randomSubMat(src, src_roi, size, srcBorder, type, -MAX_VALUE, MAX_VALUE); Border dstBorder = randomBorder(0, useRoi ? MAX_VALUE : 0); - randomSubMat(dst, dst_roi, dsize, dstBorder, type, -MAX_VALUE, MAX_VALUE); + randomSubMat(dst, dst_roi, size, dstBorder, type, -MAX_VALUE, MAX_VALUE); anchor.x = randomInt(-1, kernel.size[0]); anchor.y = randomInt(-1, kernel.size[1]);