From 27abd4d3a3ca982ed9f81e6df52921c0bacb1327 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 4 Feb 2016 19:16:05 +0300 Subject: [PATCH 1/5] Filter2D HAL interface --- .../include/opencv2/imgproc/hal/hal.hpp | 53 ++ modules/imgproc/src/deriv.cpp | 8 +- modules/imgproc/src/filter.cpp | 768 +++++++++++++----- modules/imgproc/src/filterengine.hpp | 12 +- modules/imgproc/src/hal_replacement.hpp | 24 + modules/imgproc/src/morph.cpp | 19 +- modules/imgproc/src/precomp.hpp | 1 + modules/imgproc/src/smooth.cpp | 12 +- 8 files changed, 667 insertions(+), 230 deletions(-) create mode 100644 modules/imgproc/include/opencv2/imgproc/hal/hal.hpp create mode 100644 modules/imgproc/src/hal_replacement.hpp diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp new file mode 100644 index 0000000000..be9ee497e6 --- /dev/null +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -0,0 +1,53 @@ +#ifndef CV_IMGPROC_HAL_HPP +#define CV_IMGPROC_HAL_HPP + +#include "opencv2/core/cvdef.h" +#include "opencv2/core/hal/interface.h" + +namespace cv { namespace hal { + +//! @addtogroup core_hal_functions +//! @{ + +struct FilterContext +{ + void * impl; + FilterContext() : impl(0) {} +}; + + +CV_EXPORTS +void init_filter2d(FilterContext &c, + uchar * kernel_data, size_t kernel_step, int kernel_type, + int kernel_width, int kernel_height, + int max_width, int max_height, + int stype, int dtype, + int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace); + +CV_EXPORTS +void filter2d(FilterContext & c, uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, int offset_x, int offset_y); + +CV_EXPORTS +void free_filter2d(FilterContext & c); + + +CV_EXPORTS +void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType); + +CV_EXPORTS +void sepFilter2d(FilterContext & c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, + int offset_x, int offset_y); + +CV_EXPORTS +void free_sepFilter2d(FilterContext & c); + +//! @} + +}} + +#endif // CV_IMGPROC_HAL_HPP diff --git a/modules/imgproc/src/deriv.cpp b/modules/imgproc/src/deriv.cpp index dacc23d2e8..e660d2e3b0 100644 --- a/modules/imgproc/src/deriv.cpp +++ b/modules/imgproc/src/deriv.cpp @@ -856,8 +856,12 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize, wtype, ks, kd, Point(-1,-1), 0, borderType, borderType, Scalar() ); Mat src = _src.getMat(), dst = _dst.getMat(); - int y = fx->start(src), dsty = 0, dy = 0; - fy->start(src); + Point ofs; + Size wsz(src.cols, src.rows); + src.locateROI( wsz, ofs ); + + int y = fx->start(src, wsz, ofs), dsty = 0, dy = 0; + fy->start(src, wsz, ofs); const uchar* sptr = src.ptr() + src.step[0] * y; int dy0 = std::min(std::max((int)(STRIPE_SIZE/(CV_ELEM_SIZE(stype)*src.cols)), 1), src.rows); diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index f70389b07a..d9beb69753 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -41,7 +41,9 @@ //M*/ #include "precomp.hpp" +#include "opencv2/core/opencl/ocl_defs.hpp" #include "opencl_kernels_imgproc.hpp" +#include "hal_replacement.hpp" /****************************************************************************************\ Base Image Filter @@ -158,12 +160,12 @@ void FilterEngine::init( const Ptr& _filter2D, #define VEC_ALIGN CV_MALLOC_ALIGN -int FilterEngine::start(Size _wholeSize, Rect _roi, int _maxBufRows) +int FilterEngine::start(const Size &_wholeSize, const Size &sz, const Point &ofs) { int i, j; wholeSize = _wholeSize; - roi = _roi; + roi = Rect(ofs, sz); CV_Assert( roi.x >= 0 && roi.y >= 0 && roi.width >= 0 && roi.height >= 0 && roi.x + roi.width <= wholeSize.width && roi.y + roi.height <= wholeSize.height ); @@ -172,9 +174,9 @@ int FilterEngine::start(Size _wholeSize, Rect _roi, int _maxBufRows) int bufElemSize = (int)getElemSize(bufType); const uchar* constVal = !constBorderValue.empty() ? &constBorderValue[0] : 0; - if( _maxBufRows < 0 ) - _maxBufRows = ksize.height + 3; - _maxBufRows = std::max(_maxBufRows, std::max(anchor.y, ksize.height-anchor.y-1)*2+1); + int _maxBufRows = std::max(ksize.height + 3, + std::max(anchor.y, + ksize.height-anchor.y-1)*2+1); if( maxWidth < roi.width || _maxBufRows != (int)rows.size() ) { @@ -260,29 +262,12 @@ int FilterEngine::start(Size _wholeSize, Rect _roi, int _maxBufRows) } -int FilterEngine::start(const Mat& src, const Rect& _srcRoi, - bool isolated, int maxBufRows) +int FilterEngine::start(const Mat& src, const Size &wsz, const Point &ofs) { - Rect srcRoi = _srcRoi; - - if( srcRoi == Rect(0,0,-1,-1) ) - srcRoi = Rect(0,0,src.cols,src.rows); - - CV_Assert( srcRoi.x >= 0 && srcRoi.y >= 0 && - srcRoi.width >= 0 && srcRoi.height >= 0 && - srcRoi.x + srcRoi.width <= src.cols && - srcRoi.y + srcRoi.height <= src.rows ); - - Point ofs; - Size wsz(src.cols, src.rows); - if( !isolated ) - src.locateROI( wsz, ofs ); - start( wsz, srcRoi + ofs, maxBufRows ); - + start( wsz, src.size(), ofs); return startY - ofs.y; } - int FilterEngine::remainingInputRows() const { return endY - startY - rowCount; @@ -392,28 +377,16 @@ int FilterEngine::proceed( const uchar* src, int srcstep, int count, return dy; } - -void FilterEngine::apply(const Mat& src, Mat& dst, - const Rect& _srcRoi, Point dstOfs, bool isolated) +void FilterEngine::apply(const Mat& src, Mat& dst, const Size & wsz, const Point & ofs) { CV_Assert( src.type() == srcType && dst.type() == dstType ); - Rect srcRoi = _srcRoi; - if( srcRoi == Rect(0,0,-1,-1) ) - srcRoi = Rect(0,0,src.cols,src.rows); - - if( srcRoi.area() == 0 ) - return; - - CV_Assert( dstOfs.x >= 0 && dstOfs.y >= 0 && - dstOfs.x + srcRoi.width <= dst.cols && - dstOfs.y + srcRoi.height <= dst.rows ); - - int y = start(src, srcRoi, isolated); - proceed( src.ptr() + y*src.step + srcRoi.x*src.elemSize(), - (int)src.step, endY - startY, - dst.ptr(dstOfs.y) + - dstOfs.x*dst.elemSize(), (int)dst.step ); + int y = start(src, wsz, ofs); + proceed(src.ptr() + y*src.step, + (int)src.step, + endY - startY, + dst.ptr(), + (int)dst.step ); } } @@ -4555,222 +4528,574 @@ cv::Ptr cv::createLinearFilter( int _srcType, int _dstType, _rowBorderType, _columnBorderType, _borderValue ); } -#ifdef HAVE_IPP -namespace cv + +//================================================================ +// HAL interface +//================================================================ + +using namespace cv; + +class HalFilterImpl { -static bool ipp_filter2D( InputArray _src, OutputArray _dst, int ddepth, - InputArray _kernel, Point anchor0, - double delta, int borderType ) +public: + virtual ~HalFilterImpl() {} + virtual bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int max_width, int max_height, int stype, int dtype, + int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) = 0; + virtual void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) = 0; + virtual void free() {} +}; + +struct ReplacementFilter : public HalFilterImpl { -#if !HAVE_ICV - Mat src = _src.getMat(), kernel = _kernel.getMat(); + void* ctx; + ReplacementFilter() : ctx(0) { } + bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, + int kernel_height, int max_width, int max_height, int stype, int dtype, int borderType, double delta, + int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) + { + int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, max_width, max_height, + stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace); + if (res == CV_HAL_ERROR_OK) + return true; + return false; + } + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) + { + int res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "HAL Filter returned an error"); + } + void free() + { + int res = cv_hal_filterFree(ctx); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "HAL Filter Free returned an error"); + } +}; - if( ddepth < 0 ) - ddepth = src.depth(); +#ifdef HAVE_IPP - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); - Point anchor = normalizeAnchor(anchor0, kernel.size()); +typedef IppStatus(CV_STDCALL* ippiFilterBorder)( + const void* pSrc, int srcStep, void* pDst, int dstStep, + IppiSize dstRoiSize, IppiBorderType border, const void* borderValue, + const IppiFilterBorderSpec* pSpec, Ipp8u* pBuffer); - typedef IppStatus (CV_STDCALL * ippiFilterBorder)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize dstRoiSize, - IppiBorderType border, const void * borderValue, - const IppiFilterBorderSpec* pSpec, Ipp8u* pBuffer); +static ippiFilterBorder getIppFunc(int stype) +{ + switch (stype) + { + case CV_8UC1: + return reinterpret_cast(ippiFilterBorder_8u_C1R); + case CV_8UC3: + return reinterpret_cast(ippiFilterBorder_8u_C3R); + case CV_8UC4: + return reinterpret_cast(ippiFilterBorder_8u_C4R); + case CV_16UC1: + return reinterpret_cast(ippiFilterBorder_16u_C1R); + case CV_16UC3: + return reinterpret_cast(ippiFilterBorder_16u_C3R); + case CV_16UC4: + return reinterpret_cast(ippiFilterBorder_16u_C4R); + case CV_16SC1: + return reinterpret_cast(ippiFilterBorder_16s_C1R); + case CV_16SC3: + return reinterpret_cast(ippiFilterBorder_16s_C3R); + case CV_16SC4: + return reinterpret_cast(ippiFilterBorder_16s_C4R); + case CV_32FC1: + return reinterpret_cast(ippiFilterBorder_32f_C1R); + case CV_32FC3: + return reinterpret_cast(ippiFilterBorder_32f_C3R); + case CV_32FC4: + return reinterpret_cast(ippiFilterBorder_32f_C4R); + default: + return 0; + } +} - int stype = src.type(), sdepth = CV_MAT_DEPTH(stype), cn = CV_MAT_CN(stype), - ktype = kernel.type(), kdepth = CV_MAT_DEPTH(ktype); - bool isolated = (borderType & BORDER_ISOLATED) != 0; -#if IPP_VERSION_X100 >= 900 - Point ippAnchor((kernel.cols-1)/2, (kernel.rows-1)/2); -#else - Point ippAnchor(kernel.cols >> 1, kernel.rows >> 1); -#endif - int borderTypeNI = borderType & ~BORDER_ISOLATED; - IppiBorderType ippBorderType = ippiGetBorderType(borderTypeNI); +template +struct IppFilterTrait { }; - if (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) +template <> +struct IppFilterTrait +{ + enum { kernel_type_id = CV_16SC1 }; + typedef Ipp16s kernel_type; + typedef IppStatus(CV_STDCALL* copy_fun_type)(const kernel_type* pSrc, int srcStep, kernel_type* pDst, int dstStep, IppiSize roiSize); + inline static copy_fun_type get_copy_fun() { return ippiCopy_16s_C1R; } + inline static IppStatus runInit(const kernel_type* pKernel, IppiSize kernelSize, int divisor, IppDataType dataType, int numChannels, IppRoundMode roundMode, IppiFilterBorderSpec* pSpec) { - ippiFilterBorder ippFunc = - stype == CV_8UC1 ? (ippiFilterBorder)ippiFilterBorder_8u_C1R : - stype == CV_8UC3 ? (ippiFilterBorder)ippiFilterBorder_8u_C3R : - stype == CV_8UC4 ? (ippiFilterBorder)ippiFilterBorder_8u_C4R : - stype == CV_16UC1 ? (ippiFilterBorder)ippiFilterBorder_16u_C1R : - stype == CV_16UC3 ? (ippiFilterBorder)ippiFilterBorder_16u_C3R : - stype == CV_16UC4 ? (ippiFilterBorder)ippiFilterBorder_16u_C4R : - stype == CV_16SC1 ? (ippiFilterBorder)ippiFilterBorder_16s_C1R : - stype == CV_16SC3 ? (ippiFilterBorder)ippiFilterBorder_16s_C3R : - stype == CV_16SC4 ? (ippiFilterBorder)ippiFilterBorder_16s_C4R : - stype == CV_32FC1 ? (ippiFilterBorder)ippiFilterBorder_32f_C1R : - stype == CV_32FC3 ? (ippiFilterBorder)ippiFilterBorder_32f_C3R : - stype == CV_32FC4 ? (ippiFilterBorder)ippiFilterBorder_32f_C4R : 0; - - if (sdepth == ddepth && (ktype == CV_16SC1 || ktype == CV_32FC1) && - ippFunc && (int)ippBorderType >= 0 && (!src.isSubmatrix() || isolated) && - std::fabs(delta - 0) < DBL_EPSILON && ippAnchor == anchor && dst.data != src.data) - { - IppiSize kernelSize = { kernel.cols, kernel.rows }, dstRoiSize = { dst.cols, dst.rows }; - IppDataType dataType = ippiGetDataType(ddepth), kernelType = ippiGetDataType(kdepth); - Ipp32s specSize = 0, bufsize = 0; - IppStatus status = (IppStatus)-1; + return ippiFilterBorderInit_16s(pKernel, kernelSize, divisor, dataType, numChannels, roundMode, pSpec); + } +}; - if ((status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize)) >= 0) - { - IppAutoBuffer spec(specSize); - IppAutoBuffer buffer(bufsize); - Ipp32f borderValue[4] = { 0, 0, 0, 0 }; +template <> +struct IppFilterTrait +{ + enum { kernel_type_id = CV_32FC1 }; + typedef Ipp32f kernel_type; + typedef IppStatus(CV_STDCALL* copy_fun_type)(const kernel_type* pSrc, int srcStep, kernel_type* pDst, int dstStep, IppiSize roiSize); + inline static copy_fun_type get_copy_fun() { return ippiCopy_32f_C1R; } + inline static IppStatus runInit(const kernel_type* pKernel, IppiSize kernelSize, int divisor, IppDataType dataType, int numChannels, IppRoundMode roundMode, IppiFilterBorderSpec* pSpec) + { + CV_UNUSED(divisor); + return ippiFilterBorderInit_32f(pKernel, kernelSize, dataType, numChannels, roundMode, pSpec); + } +}; - if(kdepth == CV_32F) - { - Ipp32f *pKerBuffer = (Ipp32f*)kernel.data; - IppAutoBuffer kerTmp; - int kerStep = sizeof(Ipp32f)*kernelSize.width; +template +struct IppFilter : public HalFilterImpl +{ + typedef IppFilterTrait trait; + typedef typename trait::kernel_type kernel_type; + + IppAutoBuffer spec; + IppAutoBuffer buffer; + IppAutoBuffer kernelBuffer; + IppiBorderType ippBorderType; + int src_type; + + bool init(uchar* kernel_data, size_t kernel_step, int, int kernel_width, int kernel_height, + int max_width, int max_height, int stype, int dtype, + int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) + { + Point anchor(anchor_x, anchor_y); #if IPP_VERSION_X100 >= 900 - if((int)kernel.step != kerStep) - { - kerTmp.Alloc(kerStep*kernelSize.height); - if(ippiCopy_32f_C1R((Ipp32f*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) - return false; - pKerBuffer = kerTmp; - } + Point ippAnchor((kernel_width - 1) / 2, (kernel_height - 1) / 2); #else - kerTmp.Alloc(kerStep*kernelSize.height); - Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_32FC1, kerTmp, kerStep); - flip(kernel, kerFlip, -1); - pKerBuffer = kerTmp; + Point ippAnchor(kernel_width >> 1, kernel_height >> 1); #endif + bool isIsolated = (borderType & BORDER_ISOLATED) != 0; + int borderTypeNI = borderType & ~BORDER_ISOLATED; + ippBorderType = ippiGetBorderType(borderTypeNI); + int ddepth = CV_MAT_DEPTH(dtype); + int sdepth = CV_MAT_DEPTH(stype); + + bool runIpp = true + && (borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) + && (sdepth == ddepth) + && (getIppFunc(stype)) + && ((int)ippBorderType > 0) + && (!isSubmatrix || isIsolated) + && (std::fabs(delta - 0) < DBL_EPSILON) + && (ippAnchor == anchor) + && !isInplace; + + if (!runIpp) + return false; - if((status = ippiFilterBorderInit_32f(pKerBuffer, kernelSize, - dataType, cn, ippRndFinancial, spec)) >= 0 ) - { - status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, - ippBorderType, borderValue, spec, buffer); - } - } - else if(kdepth == CV_16S) - { - Ipp16s *pKerBuffer = (Ipp16s*)kernel.data; - IppAutoBuffer kerTmp; - int kerStep = sizeof(Ipp16s)*kernelSize.width; + src_type = stype; + int cn = CV_MAT_CN(stype); + IppiSize kernelSize = { kernel_width, kernel_height }; + IppDataType dataType = ippiGetDataType(ddepth); + IppDataType kernelType = ippiGetDataType(kdepth); + Ipp32s specSize = 0; + Ipp32s bufsize = 0; + IppiSize dstRoiSize = { max_width, max_height }; + IppStatus status; + status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize); + if (status >= 0) { + kernel_type* pKerBuffer = (kernel_type*)kernel_data; + size_t good_kernel_step = sizeof(kernel_type) * static_cast(kernelSize.width); #if IPP_VERSION_X100 >= 900 - if((int)kernel.step != kerStep) - { - kerTmp.Alloc(kerStep*kernelSize.height); - if(ippiCopy_16s_C1R((Ipp16s*)kernel.data, (int)kernel.step, kerTmp, kerStep, kernelSize) < 0) - return false; - pKerBuffer = kerTmp; - } + if (kernel_step != good_kernel_step) { + kernelBuffer.Alloc((int)good_kernel_step * kernelSize.height); + status = trait::get_copy_fun()((kernel_type*)kernel_data, (int)kernel_step, kernelBuffer, (int)good_kernel_step, kernelSize); + if (status < 0) + return false; + pKerBuffer = kernelBuffer; + } #else - kerTmp.Alloc(kerStep*kernelSize.height); - Mat kerFlip(Size(kernelSize.width, kernelSize.height), CV_16SC1, kerTmp, kerStep); - flip(kernel, kerFlip, -1); - pKerBuffer = kerTmp; + kernelBuffer.Alloc(good_kernel_step * kernelSize.height); + Mat kerFlip(Size(kernelSize.width, kernelSize.height), trait::kernel_type_id, kernelBuffer, (int)good_kernel_step); + flip(kernel, kerFlip, -1); + pKerBuffer = kernelBuffer; #endif - - if((status = ippiFilterBorderInit_16s(pKerBuffer, kernelSize, - 0, dataType, cn, ippRndFinancial, spec)) >= 0) - { - status = ippFunc(src.data, (int)src.step, dst.data, (int)dst.step, dstRoiSize, - ippBorderType, borderValue, spec, buffer); - } - } - } - - if (status >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); + spec.Alloc(specSize); + buffer.Alloc(bufsize); + status = trait::runInit(pKerBuffer, kernelSize, 0, dataType, cn, ippRndFinancial, spec); + if (status >= 0) { return true; } } + return false; } -#else - CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(ddepth); CV_UNUSED(_kernel), CV_UNUSED(anchor0), CV_UNUSED(delta), CV_UNUSED(borderType); -#endif - return false; -} -} -#endif - -void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, - InputArray _kernel, Point anchor0, - double delta, int borderType ) -{ - CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, - ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType)) + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) + { + if (dst_data == src_data) + CV_Error(Error::StsBadArg, "Inplace IPP Filter2D is not supported"); + ippiFilterBorder ippFunc = getIppFunc(src_type); + IppiSize dstRoiSize = { width, height }; + kernel_type borderValue[4] = { 0, 0, 0, 0 }; + IppStatus status = ippFunc(src_data, (int)src_step, dst_data, (int)dst_step, dstRoiSize, ippBorderType, borderValue, spec, buffer); + if (status >= 0) { + CV_IMPL_ADD(CV_IMPL_IPP); + } + } +}; - Mat src = _src.getMat(), kernel = _kernel.getMat(); +#endif - if( ddepth < 0 ) - ddepth = src.depth(); +struct DftFilter : public HalFilterImpl +{ + int src_type; + int dst_type; + double delta; + Mat kernel; + Point anchor; + int borderType; + static bool isAppropriate(int stype, int dtype, int kernel_width, int kernel_height) + { #if CV_SSE2 - int dft_filter_size = ((src.depth() == CV_8U && (ddepth == CV_8U || ddepth == CV_16S)) || - (src.depth() == CV_32F && ddepth == CV_32F)) && checkHardwareSupport(CV_CPU_SSE3)? 130 : 50; + int sdepth = CV_MAT_DEPTH(stype); + int ddepth = CV_MAT_DEPTH(dtype); + int dft_filter_size = ((sdepth == CV_8U && (ddepth == CV_8U || ddepth == CV_16S)) || (sdepth == CV_32F && ddepth == CV_32F)) && checkHardwareSupport(CV_CPU_SSE3) ? 130 : 50; #else - int dft_filter_size = 50; + CV_UNUSED(stype); + CV_UNUSED(dtype); + int dft_filter_size = 50; #endif + return kernel_width * kernel_height >= dft_filter_size; + } - _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); - Mat dst = _dst.getMat(); - Point anchor = normalizeAnchor(anchor0, kernel.size()); - - CV_IPP_RUN(true, ipp_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType)); - - -#ifdef HAVE_TEGRA_OPTIMIZATION - if( tegra::useTegra() && tegra::filter2D(src, dst, kernel, anchor, delta, borderType) ) - return; -#endif + bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, + int, int, int stype, int dtype, + int borderType_, double delta_, int anchor_x, int anchor_y, bool, bool) + { + anchor = Point(anchor_x, anchor_y); + borderType = borderType_; + kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); + src_type = stype; + dst_type = dtype; + delta = delta_; + if (isAppropriate(stype, dtype, kernel_width, kernel_height)) + return true; + return false; + } - if( kernel.cols*kernel.rows >= dft_filter_size ) + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) { + Mat src(Size(width, height), src_type, src_data, src_step); + Mat dst(Size(width, height), dst_type, dst_data, dst_step); Mat temp; + int src_channels = CV_MAT_CN(src_type); + int dst_channels = CV_MAT_CN(dst_type); + int ddepth = CV_MAT_DEPTH(dst_type); // crossCorr doesn't accept non-zero delta with multiple channels - if( src.channels() != 1 && delta != 0 ) - { + 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()) ); + int corrDepth = ddepth; + if ((ddepth == CV_32F || ddepth == CV_64F) && src_data != dst_data) { + temp = Mat(Size(width, height), dst_type, dst_data, dst_step); + } else { + corrDepth = ddepth == CV_64F ? CV_64F : CV_32F; + temp.create(Size(width, height), CV_MAKETYPE(corrDepth, dst_channels)); } - crossCorr( src, kernel, temp, src.size(), - CV_MAKETYPE(corrDepth, src.channels()), - anchor, 0, borderType ); - add( temp, delta, temp ); - if ( temp.data != dst.data ) - { - temp.convertTo( dst, dst.type() ); + crossCorr(src, kernel, temp, src.size(), + 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 { + if (src_data != dst_data) + temp = Mat(Size(width, height), dst_type, dst_data, dst_step); 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.create(Size(width, height), dst_type); + crossCorr(src, kernel, temp, src.size(), + CV_MAKETYPE(ddepth, src_channels), + anchor, delta, borderType); + if (temp.data != dst_data) temp.copyTo(dst); } - return; } +}; + +struct OcvFilter : public HalFilterImpl +{ + Ptr f; + int src_type; + int dst_type; + bool isIsolated; + + bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, + int kernel_height, int, int, int stype, int dtype, int borderType, double delta, + int anchor_x, int anchor_y, bool, bool) + { + isIsolated = (borderType & BORDER_ISOLATED) != 0; + src_type = stype; + dst_type = dtype; + int borderTypeValue = borderType & ~BORDER_ISOLATED; + Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); + f = createLinearFilter(src_type, dst_type, kernel, Point(anchor_x, anchor_y), delta, + borderTypeValue); + return true; + } + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) + { + Mat src(Size(width, height), src_type, src_data, src_step); + Mat dst(Size(width, height), dst_type, dst_data, dst_step); + f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); + } +}; + +class HalSepFilterImpl +{ +public: + virtual ~HalSepFilterImpl() {} + virtual bool init(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) = 0; + virtual void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, + int offset_x, int offset_y) = 0; + virtual void free() {} +}; + +struct ReplacementSepFilter : public HalSepFilterImpl +{ + void * ctx; + ReplacementSepFilter() : ctx(0) {} + bool init(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) + { + int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, + kernelx_data, kernelx_step, kernelx_width, kernelx_height, + kernely_data, kernely_step, kernely_width, kernely_height, + anchor_x, anchor_y, delta, borderType); + if (res == CV_HAL_ERROR_OK) + { + return true; + } + return false; + } + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, + int offset_x, int offset_y) + { + int res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + } + void free() + { + int res = cv_hal_sepFilterFree(ctx); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + } +}; + +struct OcvSepFilter : public HalSepFilterImpl +{ + Ptr f; + int src_type; + int dst_type; + bool init(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) + { + src_type = stype; + dst_type = dtype; + Mat kernelX(Size(kernelx_width, kernelx_height), ktype, kernelx_data, kernelx_step); + Mat kernelY(Size(kernely_width, kernely_height), ktype, kernely_data, kernely_step); + + f = createSeparableLinearFilter( stype, dtype, kernelX, kernelY, + Point(anchor_x, anchor_y), + delta, borderType & ~BORDER_ISOLATED ); + return true; + } + void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, + int offset_x, int offset_y) + { + Mat src(Size(width, height), src_type, src_data, src_step); + Mat dst(Size(width, height), dst_type, dst_data, dst_step); + f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); + } +}; + +//=================================================================== +// HAL functions +//=================================================================== + +namespace cv { +namespace hal { + +void init_filter2d(FilterContext& c, + uchar* kernel_data, size_t kernel_step, int kernel_type, + int kernel_width, int kernel_height, + int max_width, int max_height, + int stype, int dtype, + int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) +{ + { + ReplacementFilter* impl = new ReplacementFilter(); + if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, + max_width, max_height, stype, dtype, + borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) + { + c.impl = static_cast(impl); + return; + } + delete impl; + } + +#ifdef HAVE_IPP + if (kernel_type == CV_32FC1) { + IppFilter* impl = new IppFilter(); + if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, + max_width, max_height, stype, dtype, + borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) + { + c.impl = static_cast(impl); + return; + } + delete impl; + } + + if (kernel_type == CV_16SC1) { + IppFilter* impl = new IppFilter(); + if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, + max_width, max_height, stype, dtype, + borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) + { + c.impl = static_cast(impl); + return; + } + delete impl; + } +#endif + + if (DftFilter::isAppropriate(stype, dtype, kernel_width, kernel_height)) + { + DftFilter* impl = new DftFilter(); + if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, + max_width, max_height, stype, dtype, + borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) + { + c.impl = static_cast(impl); + return; + } + delete impl; + } + + { + OcvFilter* impl = new OcvFilter(); + impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, + max_width, max_height, stype, dtype, + borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace); + c.impl = static_cast(impl); + } +} + +void filter2d(FilterContext& c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) +{ + HalFilterImpl* impl = static_cast(c.impl); + impl->run(src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); +} + +void free_filter2d(FilterContext& c) +{ + HalFilterImpl* impl = static_cast(c.impl); + impl->free(); + delete impl; + c.impl = 0; +} + +//--------------------------------------------------------------- + +void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) +{ + { + ReplacementSepFilter * impl = new ReplacementSepFilter(); + if (impl->init(stype, dtype, ktype, + kernelx_data, kernelx_step, kernelx_width, kernelx_height, + kernely_data, kernely_step, kernely_width, kernely_height, + anchor_x, anchor_y, delta, borderType)) + { + c.impl = impl; + return; + } + delete impl; + } + { + OcvSepFilter * impl = new OcvSepFilter(); + impl->init(stype, dtype, ktype, + kernelx_data, kernelx_step, kernelx_width, kernelx_height, + kernely_data, kernely_step, kernely_width, kernely_height, + anchor_x, anchor_y, delta, borderType); + c.impl = impl; + } +} - Ptr f = createLinearFilter(src.type(), dst.type(), kernel, - anchor, delta, borderType & ~BORDER_ISOLATED ); - f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 ); +void sepFilter2d(FilterContext & c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int full_width, int full_height, + int offset_x, int offset_y) +{ + HalSepFilterImpl * impl = static_cast(c.impl); + impl->run(src_data, src_step, dst_data, dst_step, + width, height, full_width, full_height, + offset_x, offset_y); } +void free_sepFilter2d(FilterContext & c) +{ + HalSepFilterImpl * impl = static_cast(c.impl); + impl->free(); + delete impl; + c.impl = 0; +} + +} // cv::hal:: +} // cv:: + +//================================================================ +// Main interface +//================================================================ + +void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, + InputArray _kernel, Point anchor0, + double delta, int borderType ) +{ + CV_OCL_RUN(_dst.isUMat() && _src.dims() <= 2, + ocl_filter2D(_src, _dst, ddepth, _kernel, anchor0, delta, borderType)) + + Mat src = _src.getMat(), kernel = _kernel.getMat(); + + if( ddepth < 0 ) + ddepth = src.depth(); + + _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); + Mat dst = _dst.getMat(); + Point anchor = normalizeAnchor(anchor0, kernel.size()); + + Point ofs; + Size wsz(src.cols, src.rows); + if( (borderType & BORDER_ISOLATED) == 0 ) + src.locateROI( wsz, ofs ); + + hal::FilterContext c; + hal::init_filter2d(c, + kernel.data, kernel.step, kernel.type(), kernel.cols, kernel.rows, + dst.cols, dst.rows, src.type(), dst.type(), + borderType, delta, anchor.x, anchor.y, src.isSubmatrix(), src.data == dst.data); + hal::filter2d(c, src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); + hal::free_filter2d(c); +} void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernelX, InputArray _kernelY, Point anchor, @@ -4787,9 +5112,20 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, _dst.create( src.size(), CV_MAKETYPE(ddepth, src.channels()) ); Mat dst = _dst.getMat(); - Ptr f = createSeparableLinearFilter(src.type(), - dst.type(), kernelX, kernelY, anchor, delta, borderType & ~BORDER_ISOLATED ); - f->apply(src, dst, Rect(0,0,-1,-1), Point(), (borderType & BORDER_ISOLATED) != 0 ); + Point ofs; + Size wsz(src.cols, src.rows); + if( (borderType & BORDER_ISOLATED) == 0 ) + src.locateROI( wsz, ofs ); + + CV_Assert(kernelX.type() == kernelY.type()); + + hal::FilterContext c; + hal::init_sepFilter2d(c, src.type(), dst.type(), kernelX.type(), + kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, + kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, + anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); + hal::sepFilter2d(c, src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); + hal::free_sepFilter2d(c); } diff --git a/modules/imgproc/src/filterengine.hpp b/modules/imgproc/src/filterengine.hpp index 68875c078c..fbb3c1ace4 100644 --- a/modules/imgproc/src/filterengine.hpp +++ b/modules/imgproc/src/filterengine.hpp @@ -228,19 +228,17 @@ public: int _rowBorderType = BORDER_REPLICATE, int _columnBorderType = -1, const Scalar& _borderValue = Scalar()); + //! starts filtering of the specified ROI of an image of size wholeSize. - virtual int start(Size wholeSize, Rect roi, int maxBufRows = -1); + virtual int start(const cv::Size &wholeSize, const cv::Size &sz, const cv::Point &ofs); //! starts filtering of the specified ROI of the specified image. - virtual int start(const Mat& src, const Rect& srcRoi = Rect(0,0,-1,-1), - bool isolated = false, int maxBufRows = -1); + virtual int start(const Mat& src, const cv::Size &wsz, const cv::Point &ofs); //! processes the next srcCount rows of the image. virtual int proceed(const uchar* src, int srcStep, int srcCount, uchar* dst, int dstStep); //! applies filter to the specified ROI of the image. if srcRoi=(0,0,-1,-1), the whole image is filtered. - virtual void apply( const Mat& src, Mat& dst, - const Rect& srcRoi = Rect(0,0,-1,-1), - Point dstOfs = Point(0,0), - bool isolated = false); + virtual void apply(const Mat& src, Mat& dst, const cv::Size &wsz, const cv::Point &ofs); + //! returns true if the filter is separable bool isSeparable() const { return !filter2D; } //! returns the number diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp new file mode 100644 index 0000000000..29f35edb59 --- /dev/null +++ b/modules/imgproc/src/hal_replacement.hpp @@ -0,0 +1,24 @@ +#ifndef OPENCV_IMGPROC_HAL_REPLACEMENT_HPP +#define OPENCV_IMGPROC_HAL_REPLACEMENT_HPP + +#include "opencv2/core/hal/interface.h" + +inline int hal_ni_filterInit(void **, uchar *, size_t, int, int, int, int, int, int, int, int, double, int, int, bool, bool) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_filter(void *, uchar *, size_t, uchar *, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_filterFree(void *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +#define cv_hal_filterInit hal_ni_filterInit +#define cv_hal_filter hal_ni_filter +#define cv_hal_filterFree hal_ni_filterFree + +inline int hal_ni_sepFilterInit(void **, int, int, int, uchar *, size_t, int, int, uchar *, size_t, int, int, int, int, double, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilter(void *, uchar *, size_t, uchar*, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilterFree(void *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +#define cv_hal_sepFilterInit hal_ni_sepFilterInit +#define cv_hal_sepFilter hal_ni_sepFilter +#define cv_hal_sepFilterFree hal_ni_sepFilterFree + +#include "custom_hal.hpp" + +#endif // OPENCV_IMGPROC_HAL_REPLACEMENT_HPP diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 49ddb2dd5c..c68ccc9d2d 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1117,9 +1117,22 @@ public: Ptr f = createMorphologyFilter(op, src.type(), kernel, anchor, rowBorderType, columnBorderType, borderValue ); - f->apply( srcStripe, dstStripe ); - for( int i = 1; i < iterations; i++ ) - f->apply( dstStripe, dstStripe ); + { + Point ofs; + Size wsz(srcStripe.cols, srcStripe.rows); + srcStripe.locateROI( wsz, ofs ); + + f->apply( srcStripe, dstStripe, wsz, ofs ); + } + + { + Point ofs; + Size wsz(dstStripe.cols, dstStripe.rows); + dstStripe.locateROI( wsz, ofs ); + + for( int i = 1; i < iterations; i++ ) + f->apply( dstStripe, dstStripe, wsz, ofs ); + } } private: diff --git a/modules/imgproc/src/precomp.hpp b/modules/imgproc/src/precomp.hpp index ed27eeabb5..3e21b9eae1 100644 --- a/modules/imgproc/src/precomp.hpp +++ b/modules/imgproc/src/precomp.hpp @@ -50,6 +50,7 @@ #include "opencv2/core/private.hpp" #include "opencv2/core/ocl.hpp" #include "opencv2/core/hal/hal.hpp" +#include "opencv2/imgproc/hal/hal.hpp" #include #include diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index df744effd4..f401a679d5 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -1439,7 +1439,11 @@ void cv::boxFilter( InputArray _src, OutputArray _dst, int ddepth, Ptr f = createBoxFilter( src.type(), dst.type(), ksize, anchor, normalize, borderType ); - f->apply( src, dst ); + Point ofs; + Size wsz(src.cols, src.rows); + src.locateROI( wsz, ofs ); + + f->apply( src, dst, wsz, ofs ); } @@ -1561,7 +1565,11 @@ void cv::sqrBoxFilter( InputArray _src, OutputArray _dst, int ddepth, Ptr f = makePtr(Ptr(), rowFilter, columnFilter, srcType, dstType, sumType, borderType ); - f->apply( src, dst ); + Point ofs; + Size wsz(src.cols, src.rows); + src.locateROI( wsz, ofs ); + + f->apply( src, dst, wsz, ofs ); } From 8414c6518f0fffd2f90ae29c8c9e80d99eb98349 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Sat, 20 Feb 2016 12:29:23 +0300 Subject: [PATCH 2/5] Fixed build with older ippicv --- modules/imgproc/src/filter.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index d9beb69753..c09818580f 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4575,7 +4575,7 @@ struct ReplacementFilter : public HalFilterImpl }; #ifdef HAVE_IPP - +#if !HAVE_ICV typedef IppStatus(CV_STDCALL* ippiFilterBorder)( const void* pSrc, int srcStep, void* pDst, int dstStep, IppiSize dstRoiSize, IppiBorderType border, const void* borderValue, @@ -4735,7 +4735,7 @@ struct IppFilter : public HalFilterImpl } } }; - +#endif #endif struct DftFilter : public HalFilterImpl @@ -4952,6 +4952,7 @@ void init_filter2d(FilterContext& c, } #ifdef HAVE_IPP +#if !HAVE_ICV if (kernel_type == CV_32FC1) { IppFilter* impl = new IppFilter(); if (impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, @@ -4975,6 +4976,7 @@ void init_filter2d(FilterContext& c, } delete impl; } +#endif #endif if (DftFilter::isAppropriate(stype, dtype, kernel_width, kernel_height)) From 85b2c2ae584ca5d928a7e8c7483355f35a435693 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Wed, 24 Feb 2016 19:31:22 +0300 Subject: [PATCH 3/5] Fixed build with older standalone IPP versions --- modules/imgproc/src/filter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index c09818580f..d748af5d81 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4709,6 +4709,7 @@ struct IppFilter : public HalFilterImpl #else kernelBuffer.Alloc(good_kernel_step * kernelSize.height); Mat kerFlip(Size(kernelSize.width, kernelSize.height), trait::kernel_type_id, kernelBuffer, (int)good_kernel_step); + Mat kernel(Size(kernel_width, kernel_height), trait::kernel_type_id, kernel_data, kernel_step); flip(kernel, kerFlip, -1); pKerBuffer = kernelBuffer; #endif From 17cd1dac06441366cfe89566bffb2e883b12730b Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Tue, 1 Mar 2016 18:48:41 +0300 Subject: [PATCH 4/5] HAL Filter2D interface: Updated according to comments --- .../include/opencv2/imgproc/hal/hal.hpp | 56 ++--- modules/imgproc/src/filter.cpp | 209 +++++++----------- modules/imgproc/src/hal_replacement.hpp | 14 +- 3 files changed, 106 insertions(+), 173 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp index be9ee497e6..cfd5841501 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -2,6 +2,7 @@ #define CV_IMGPROC_HAL_HPP #include "opencv2/core/cvdef.h" +#include "opencv2/core/cvstd.hpp" #include "opencv2/core/hal/interface.h" namespace cv { namespace hal { @@ -9,43 +10,30 @@ namespace cv { namespace hal { //! @addtogroup core_hal_functions //! @{ -struct FilterContext +struct CV_EXPORTS Filter2D { - void * impl; - FilterContext() : impl(0) {} + static Ptr createFilter2D(uchar * kernel_data, size_t kernel_step, int kernel_type, + int kernel_width, int kernel_height, + int max_width, int max_height, + int stype, int dtype, + int borderType, double delta, + int anchor_x, int anchor_y, + bool isSubmatrix, bool isInplace); + static Ptr createSepFilter2D(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, + int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, + int kernely_width, int kernely_height, + int anchor_x, int anchor_y, + double delta, int borderType); + virtual void apply(uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int full_width, int full_height, + int offset_x, int offset_y) = 0; + virtual ~Filter2D() {} }; - -CV_EXPORTS -void init_filter2d(FilterContext &c, - uchar * kernel_data, size_t kernel_step, int kernel_type, - int kernel_width, int kernel_height, - int max_width, int max_height, - int stype, int dtype, - int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace); - -CV_EXPORTS -void filter2d(FilterContext & c, uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, - int width, int height, int full_width, int full_height, int offset_x, int offset_y); - -CV_EXPORTS -void free_filter2d(FilterContext & c); - - -CV_EXPORTS -void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, - int anchor_x, int anchor_y, double delta, int borderType); - -CV_EXPORTS -void sepFilter2d(FilterContext & c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, - int width, int height, int full_width, int full_height, - int offset_x, int offset_y); - -CV_EXPORTS -void free_sepFilter2d(FilterContext & c); - //! @} }} diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index d748af5d81..799f152738 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4535,42 +4535,37 @@ cv::Ptr cv::createLinearFilter( int _srcType, int _dstType, using namespace cv; -class HalFilterImpl +struct ReplacementFilter : public hal::Filter2D { -public: - virtual ~HalFilterImpl() {} - virtual bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, - int max_width, int max_height, int stype, int dtype, - int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) = 0; - virtual void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) = 0; - virtual void free() {} -}; - -struct ReplacementFilter : public HalFilterImpl -{ - void* ctx; - ReplacementFilter() : ctx(0) { } + cvhalFilter2D* ctx; + bool isInitialized; + ReplacementFilter() : ctx(0), isInitialized(false) { } bool init(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, int max_width, int max_height, int stype, int dtype, int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) { int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace); - if (res == CV_HAL_ERROR_OK) - return true; - return false; + isInitialized = (res == CV_HAL_ERROR_OK); + return isInitialized; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) { - int res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "HAL Filter returned an error"); + if (isInitialized) + { + int res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "HAL Filter returned an error"); + } } - void free() + ~ReplacementFilter() { - int res = cv_hal_filterFree(ctx); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "HAL Filter Free returned an error"); + if (isInitialized) + { + int res = cv_hal_filterFree(ctx); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "HAL Filter Free returned an error"); + } } }; @@ -4645,7 +4640,7 @@ struct IppFilterTrait }; template -struct IppFilter : public HalFilterImpl +struct IppFilter : public hal::Filter2D { typedef IppFilterTrait trait; typedef typename trait::kernel_type kernel_type; @@ -4723,7 +4718,7 @@ struct IppFilter : public HalFilterImpl return false; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) { if (dst_data == src_data) CV_Error(Error::StsBadArg, "Inplace IPP Filter2D is not supported"); @@ -4739,7 +4734,7 @@ struct IppFilter : public HalFilterImpl #endif #endif -struct DftFilter : public HalFilterImpl +struct DftFilter : public hal::Filter2D { int src_type; int dst_type; @@ -4777,7 +4772,7 @@ struct DftFilter : public HalFilterImpl return false; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) { Mat src(Size(width, height), src_type, src_data, src_step); Mat dst(Size(width, height), dst_type, dst_data, dst_step); @@ -4819,7 +4814,7 @@ struct DftFilter : public HalFilterImpl } }; -struct OcvFilter : public HalFilterImpl +struct OcvFilter : public hal::Filter2D { Ptr f; int src_type; @@ -4839,7 +4834,7 @@ struct OcvFilter : public HalFilterImpl borderTypeValue); return true; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) { Mat src(Size(width, height), src_type, src_data, src_step); Mat dst(Size(width, height), dst_type, dst_data, dst_step); @@ -4847,56 +4842,47 @@ struct OcvFilter : public HalFilterImpl } }; -class HalSepFilterImpl -{ -public: - virtual ~HalSepFilterImpl() {} - virtual bool init(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, - int anchor_x, int anchor_y, double delta, int borderType) = 0; - virtual void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, - int width, int height, int full_width, int full_height, - int offset_x, int offset_y) = 0; - virtual void free() {} -}; -struct ReplacementSepFilter : public HalSepFilterImpl +struct ReplacementSepFilter : public hal::Filter2D { - void * ctx; - ReplacementSepFilter() : ctx(0) {} + cvhalFilter2D *ctx; + bool isInitialized; + ReplacementSepFilter() : ctx(0), isInitialized(false) {} bool init(int stype, int dtype, int ktype, uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, int anchor_x, int anchor_y, double delta, int borderType) { int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, - kernelx_data, kernelx_step, kernelx_width, kernelx_height, - kernely_data, kernely_step, kernely_width, kernely_height, - anchor_x, anchor_y, delta, borderType); - if (res == CV_HAL_ERROR_OK) - { - return true; - } - return false; + kernelx_data, kernelx_step, kernelx_width, kernelx_height, + kernely_data, kernely_step, kernely_width, kernely_height, + anchor_x, anchor_y, delta, borderType); + isInitialized = (res == CV_HAL_ERROR_OK); + return isInitialized; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) { - int res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + if (isInitialized) + { + int res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + } } - void free() + ~ReplacementSepFilter() { - int res = cv_hal_sepFilterFree(ctx); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + if (isInitialized) + { + int res = cv_hal_sepFilterFree(ctx); + if (res != CV_HAL_ERROR_OK) + CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); + } } }; -struct OcvSepFilter : public HalSepFilterImpl +struct OcvSepFilter : public hal::Filter2D { Ptr f; int src_type; @@ -4916,7 +4902,7 @@ struct OcvSepFilter : public HalSepFilterImpl delta, borderType & ~BORDER_ISOLATED ); return true; } - void run(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) { @@ -4933,12 +4919,11 @@ struct OcvSepFilter : public HalSepFilterImpl namespace cv { namespace hal { -void init_filter2d(FilterContext& c, - uchar* kernel_data, size_t kernel_step, int kernel_type, - int kernel_width, int kernel_height, - int max_width, int max_height, - int stype, int dtype, - int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) +Ptr Filter2D::createFilter2D(uchar* kernel_data, size_t kernel_step, int kernel_type, + int kernel_width, int kernel_height, + int max_width, int max_height, + int stype, int dtype, + int borderType, double delta, int anchor_x, int anchor_y, bool isSubmatrix, bool isInplace) { { ReplacementFilter* impl = new ReplacementFilter(); @@ -4946,8 +4931,7 @@ void init_filter2d(FilterContext& c, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) { - c.impl = static_cast(impl); - return; + return Ptr(impl); } delete impl; } @@ -4960,8 +4944,7 @@ void init_filter2d(FilterContext& c, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) { - c.impl = static_cast(impl); - return; + return Ptr(impl); } delete impl; } @@ -4972,8 +4955,7 @@ void init_filter2d(FilterContext& c, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) { - c.impl = static_cast(impl); - return; + return Ptr(impl); } delete impl; } @@ -4987,8 +4969,7 @@ void init_filter2d(FilterContext& c, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace)) { - c.impl = static_cast(impl); - return; + return Ptr(impl); } delete impl; } @@ -4998,30 +4979,16 @@ void init_filter2d(FilterContext& c, impl->init(kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, max_width, max_height, stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, isInplace); - c.impl = static_cast(impl); + return Ptr(impl); } } -void filter2d(FilterContext& c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int full_width, int full_height, int offset_x, int offset_y) -{ - HalFilterImpl* impl = static_cast(c.impl); - impl->run(src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); -} - -void free_filter2d(FilterContext& c) -{ - HalFilterImpl* impl = static_cast(c.impl); - impl->free(); - delete impl; - c.impl = 0; -} - //--------------------------------------------------------------- -void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, - int anchor_x, int anchor_y, double delta, int borderType) +Ptr Filter2D::createSepFilter2D(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) { { ReplacementSepFilter * impl = new ReplacementSepFilter(); @@ -5030,8 +4997,7 @@ void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, kernely_data, kernely_step, kernely_width, kernely_height, anchor_x, anchor_y, delta, borderType)) { - c.impl = impl; - return; + return Ptr(impl); } delete impl; } @@ -5041,28 +5007,10 @@ void init_sepFilter2d(FilterContext & c, int stype, int dtype, int ktype, kernelx_data, kernelx_step, kernelx_width, kernelx_height, kernely_data, kernely_step, kernely_width, kernely_height, anchor_x, anchor_y, delta, borderType); - c.impl = impl; + return Ptr(impl); } } -void sepFilter2d(FilterContext & c, uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, - int width, int height, int full_width, int full_height, - int offset_x, int offset_y) -{ - HalSepFilterImpl * impl = static_cast(c.impl); - impl->run(src_data, src_step, dst_data, dst_step, - width, height, full_width, full_height, - offset_x, offset_y); -} - -void free_sepFilter2d(FilterContext & c) -{ - HalSepFilterImpl * impl = static_cast(c.impl); - impl->free(); - delete impl; - c.impl = 0; -} - } // cv::hal:: } // cv:: @@ -5091,13 +5039,10 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, if( (borderType & BORDER_ISOLATED) == 0 ) src.locateROI( wsz, ofs ); - hal::FilterContext c; - hal::init_filter2d(c, - kernel.data, kernel.step, kernel.type(), kernel.cols, kernel.rows, - dst.cols, dst.rows, src.type(), dst.type(), - borderType, delta, anchor.x, anchor.y, src.isSubmatrix(), src.data == dst.data); - hal::filter2d(c, src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); - hal::free_filter2d(c); + Ptr c = hal::Filter2D::createFilter2D(kernel.data, kernel.step, kernel.type(), kernel.cols, kernel.rows, + dst.cols, dst.rows, src.type(), dst.type(), + borderType, delta, anchor.x, anchor.y, src.isSubmatrix(), src.data == dst.data); + c->apply(src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); } void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, @@ -5122,13 +5067,11 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, CV_Assert(kernelX.type() == kernelY.type()); - hal::FilterContext c; - hal::init_sepFilter2d(c, src.type(), dst.type(), kernelX.type(), - kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, - kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, - anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); - hal::sepFilter2d(c, src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); - hal::free_sepFilter2d(c); + Ptr c = hal::Filter2D::createSepFilter2D(src.type(), dst.type(), kernelX.type(), + kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, + kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, + anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); + c->apply(src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); } diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index 29f35edb59..6d944b1537 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -3,17 +3,19 @@ #include "opencv2/core/hal/interface.h" -inline int hal_ni_filterInit(void **, uchar *, size_t, int, int, int, int, int, int, int, int, double, int, int, bool, bool) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } -inline int hal_ni_filter(void *, uchar *, size_t, uchar *, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } -inline int hal_ni_filterFree(void *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +struct cvhalFilter2D {}; + +inline int hal_ni_filterInit(cvhalFilter2D **, uchar *, size_t, int, int, int, int, int, int, int, int, double, int, int, bool, bool) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_filter(cvhalFilter2D *, uchar *, size_t, uchar *, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_filterFree(cvhalFilter2D *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } #define cv_hal_filterInit hal_ni_filterInit #define cv_hal_filter hal_ni_filter #define cv_hal_filterFree hal_ni_filterFree -inline int hal_ni_sepFilterInit(void **, int, int, int, uchar *, size_t, int, int, uchar *, size_t, int, int, int, int, double, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } -inline int hal_ni_sepFilter(void *, uchar *, size_t, uchar*, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } -inline int hal_ni_sepFilterFree(void *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilterInit(cvhalFilter2D **, int, int, int, uchar *, size_t, int, int, uchar *, size_t, int, int, int, int, double, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilter(cvhalFilter2D *, uchar *, size_t, uchar*, size_t, int, int, int, int, int, int) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } +inline int hal_ni_sepFilterFree(cvhalFilter2D *) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } #define cv_hal_sepFilterInit hal_ni_sepFilterInit #define cv_hal_sepFilter hal_ni_sepFilter From 98fff4a6013a4ce7f945cb866225f44e17b3b2dd Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Thu, 3 Mar 2016 18:55:47 +0300 Subject: [PATCH 5/5] Added separate hal::SepFilter2D class --- .../include/opencv2/imgproc/hal/hal.hpp | 38 ++++++++++++------- modules/imgproc/src/filter.cpp | 32 ++++++++-------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp index cfd5841501..0b0886f6d9 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -12,20 +12,13 @@ namespace cv { namespace hal { struct CV_EXPORTS Filter2D { - static Ptr createFilter2D(uchar * kernel_data, size_t kernel_step, int kernel_type, - int kernel_width, int kernel_height, - int max_width, int max_height, - int stype, int dtype, - int borderType, double delta, - int anchor_x, int anchor_y, - bool isSubmatrix, bool isInplace); - static Ptr createSepFilter2D(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, - int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, - int kernely_width, int kernely_height, - int anchor_x, int anchor_y, - double delta, int borderType); + static Ptr create(uchar * kernel_data, size_t kernel_step, int kernel_type, + int kernel_width, int kernel_height, + int max_width, int max_height, + int stype, int dtype, + int borderType, double delta, + int anchor_x, int anchor_y, + bool isSubmatrix, bool isInplace); virtual void apply(uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, @@ -34,6 +27,23 @@ struct CV_EXPORTS Filter2D virtual ~Filter2D() {} }; +struct CV_EXPORTS SepFilter2D +{ + static Ptr create(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, + int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, + int kernely_width, int kernely_height, + int anchor_x, int anchor_y, + double delta, int borderType); + virtual void apply(uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int full_width, int full_height, + int offset_x, int offset_y) = 0; + virtual ~SepFilter2D() {} +}; + //! @} }} diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index 799f152738..13d02def88 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4843,7 +4843,7 @@ struct OcvFilter : public hal::Filter2D }; -struct ReplacementSepFilter : public hal::Filter2D +struct ReplacementSepFilter : public hal::SepFilter2D { cvhalFilter2D *ctx; bool isInitialized; @@ -4882,7 +4882,7 @@ struct ReplacementSepFilter : public hal::Filter2D } }; -struct OcvSepFilter : public hal::Filter2D +struct OcvSepFilter : public hal::SepFilter2D { Ptr f; int src_type; @@ -4919,7 +4919,7 @@ struct OcvSepFilter : public hal::Filter2D namespace cv { namespace hal { -Ptr Filter2D::createFilter2D(uchar* kernel_data, size_t kernel_step, int kernel_type, +Ptr Filter2D::create(uchar* kernel_data, size_t kernel_step, int kernel_type, int kernel_width, int kernel_height, int max_width, int max_height, int stype, int dtype, @@ -4985,10 +4985,10 @@ Ptr Filter2D::createFilter2D(uchar* kernel_data, size_t kernel_st //--------------------------------------------------------------- -Ptr Filter2D::createSepFilter2D(int stype, int dtype, int ktype, - uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, - uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, - int anchor_x, int anchor_y, double delta, int borderType) +Ptr SepFilter2D::create(int stype, int dtype, int ktype, + uchar * kernelx_data, size_t kernelx_step, int kernelx_width, int kernelx_height, + uchar * kernely_data, size_t kernely_step, int kernely_width, int kernely_height, + int anchor_x, int anchor_y, double delta, int borderType) { { ReplacementSepFilter * impl = new ReplacementSepFilter(); @@ -4997,7 +4997,7 @@ Ptr Filter2D::createSepFilter2D(int stype, int dtype, int ktype, kernely_data, kernely_step, kernely_width, kernely_height, anchor_x, anchor_y, delta, borderType)) { - return Ptr(impl); + return Ptr(impl); } delete impl; } @@ -5007,7 +5007,7 @@ Ptr Filter2D::createSepFilter2D(int stype, int dtype, int ktype, kernelx_data, kernelx_step, kernelx_width, kernelx_height, kernely_data, kernely_step, kernely_width, kernely_height, anchor_x, anchor_y, delta, borderType); - return Ptr(impl); + return Ptr(impl); } } @@ -5039,9 +5039,9 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, if( (borderType & BORDER_ISOLATED) == 0 ) src.locateROI( wsz, ofs ); - Ptr c = hal::Filter2D::createFilter2D(kernel.data, kernel.step, kernel.type(), kernel.cols, kernel.rows, - dst.cols, dst.rows, src.type(), dst.type(), - borderType, delta, anchor.x, anchor.y, src.isSubmatrix(), src.data == dst.data); + Ptr c = hal::Filter2D::create(kernel.data, kernel.step, kernel.type(), kernel.cols, kernel.rows, + dst.cols, dst.rows, src.type(), dst.type(), + borderType, delta, anchor.x, anchor.y, src.isSubmatrix(), src.data == dst.data); c->apply(src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); } @@ -5067,10 +5067,10 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, CV_Assert(kernelX.type() == kernelY.type()); - Ptr c = hal::Filter2D::createSepFilter2D(src.type(), dst.type(), kernelX.type(), - kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, - kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, - anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); + Ptr c = hal::SepFilter2D::create(src.type(), dst.type(), kernelX.type(), + kernelX.data, kernelX.step, kernelX.cols, kernelX.rows, + kernelY.data, kernelY.step, kernelY.cols, kernelY.rows, + anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); c->apply(src.data, src.step, dst.data, dst.step, dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y); }