From c4c1c4c9bbddc2541844a094a0cbdff949655997 Mon Sep 17 00:00:00 2001 From: Maksim Shabunin Date: Mon, 27 Feb 2017 12:13:31 +0300 Subject: [PATCH] Replaced several hal:: classes with functions, marked old variants deprecated --- .../include/opencv2/imgproc/hal/hal.hpp | 104 ++- modules/imgproc/src/filter.cpp | 651 +++++++++--------- modules/imgproc/src/morph.cpp | 524 +++++++------- 3 files changed, 625 insertions(+), 654 deletions(-) diff --git a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp index fc6b9d8d0a..5523df27d9 100644 --- a/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp +++ b/modules/imgproc/include/opencv2/imgproc/hal/hal.hpp @@ -10,53 +10,93 @@ namespace cv { namespace hal { //! @addtogroup imgproc_hal_functions //! @{ +//--------------------------- +//! @cond IGNORED + struct CV_EXPORTS Filter2D { - 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, - int full_width, int full_height, - int offset_x, int offset_y) = 0; + CV_DEPRECATED static Ptr create(uchar * , size_t , int , + int , int , + int , int , + int , int , + int , double , + int , int , + bool , bool ); + virtual void apply(uchar * , size_t , + uchar * , size_t , + int , int , + int , int , + int , int ) = 0; virtual ~Filter2D() {} }; struct CV_EXPORTS SepFilter2D { - static Ptr create(int stype, int dtype, int ktype, - uchar * kernelx_data, int kernelx_len, - uchar * kernely_data, int kernely_len, - 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; + CV_DEPRECATED static Ptr create(int , int , int , + uchar * , int , + uchar * , int , + int , int , + double , int ); + virtual void apply(uchar * , size_t , + uchar * , size_t , + int , int , + int , int , + int , int ) = 0; virtual ~SepFilter2D() {} }; -struct CV_EXPORTS Morph +struct CV_EXPORTS Morph { - static Ptr create(int op, int src_type, int dst_type, int max_width, int max_height, - int kernel_type, uchar * kernel_data, size_t kernel_step, - int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double borderValue[4], - int iterations, bool isSubmatrix, bool allowInplace); - virtual void apply(uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, - int roi_width, int roi_height, int roi_x, int roi_y, - int roi_width2, int roi_height2, int roi_x2, int roi_y2) = 0; + CV_DEPRECATED static Ptr create(int , int , int , int , int , + int , uchar * , size_t , + int , int , + int , int , + int , const double *, + int , bool , bool ); + virtual void apply(uchar * , size_t , uchar * , size_t , int , int , + int , int , int , int , + int , int , int , int ) = 0; virtual ~Morph() {} }; +//! @endcond +//--------------------------- + +CV_EXPORTS void filter2D(int stype, int dtype, int kernel_type, + 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, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType, + bool isSubmatrix); + +CV_EXPORTS void sepFilter2D(int stype, int dtype, int ktype, + 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, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, + int anchor_x, int anchor_y, + double delta, int borderType); + +CV_EXPORTS void morph(int op, int src_type, int dst_type, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int roi_width, int roi_height, int roi_x, int roi_y, + int roi_width2, int roi_height2, int roi_x2, int roi_y2, + int kernel_type, uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], + int iterations, bool isSubmatrix); + CV_EXPORTS void resize(int src_type, const uchar * src_data, size_t src_step, int src_width, int src_height, diff --git a/modules/imgproc/src/filter.cpp b/modules/imgproc/src/filter.cpp index e379df2bb0..641f960ab3 100644 --- a/modules/imgproc/src/filter.cpp +++ b/modules/imgproc/src/filter.cpp @@ -4509,39 +4509,29 @@ cv::Ptr cv::createLinearFilter( int _srcType, int _dstType, using namespace cv; -struct ReplacementFilter : public hal::Filter2D +static bool replacementFilter2D(int stype, int dtype, int kernel_type, + 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, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType, bool isSubmatrix) { 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); - isInitialized = (res == CV_HAL_ERROR_OK); - return isInitialized; - } - 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) - { - 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"); - } - } - ~ReplacementFilter() - { - if (isInitialized) - { - int res = cv_hal_filterFree(ctx); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "HAL Filter Free returned an error"); - } - } -}; + int res = cv_hal_filterInit(&ctx, kernel_data, kernel_step, kernel_type, kernel_width, kernel_height, width, height, + stype, dtype, borderType, delta, anchor_x, anchor_y, isSubmatrix, src_data == dst_data); + if (res != CV_HAL_ERROR_OK) + return false; + res = cv_hal_filter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + bool success = (res == CV_HAL_ERROR_OK); + res = cv_hal_filterFree(ctx); + if (res != CV_HAL_ERROR_OK) + return false; + return success; +} #ifdef HAVE_IPP typedef IppStatus(CV_STDCALL* IppiFilterBorder)( @@ -4613,8 +4603,17 @@ struct IppFilterTrait }; template -struct IppFilter : public hal::Filter2D +static bool ippFilter2D(int stype, int dtype, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType, bool isSubmatrix) { + CV_INSTRUMENT_REGION_IPP(); + typedef IppFilterTrait trait; typedef typename trait::kernel_type kernel_type; @@ -4624,105 +4623,92 @@ struct IppFilter : public hal::Filter2D 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); + Point anchor(anchor_x, anchor_y); #if IPP_VERSION_X100 >= 900 - Point ippAnchor((kernel_width - 1) / 2, (kernel_height - 1) / 2); + Point ippAnchor((kernel_width - 1) / 2, (kernel_height - 1) / 2); #else - Point ippAnchor(kernel_width >> 1, kernel_height >> 1); + 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 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); #if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 < 201702 // IPP bug with 1x1 kernel - if(kernel_width == 1 && kernel_height == 1) - return false; + if(kernel_width == 1 && kernel_height == 1) + return false; #endif - 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; + 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) + && src_data != dst_data; - if (!runIpp) - return false; + if (!runIpp) + return false; - 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); + 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 = { width, height }; + IppStatus status; + status = ippiFilterBorderGetSize(kernelSize, dstRoiSize, dataType, kernelType, cn, &specSize, &bufsize); + if (status < 0) + return false; + + 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 (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; - } + 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 - 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; + 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 - spec.Alloc(specSize); - buffer.Alloc(bufsize); - status = trait::runInit(pKerBuffer, kernelSize, 0, dataType, cn, ippRndFinancial, spec); - if (status >= 0) { - return true; - } - } + spec.Alloc(specSize); + buffer.Alloc(bufsize); + status = trait::runInit(pKerBuffer, kernelSize, 0, dataType, cn, ippRndFinancial, spec); + if (status < 0) { return false; } - - void apply(uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int, int, int, int) - { - CV_INSTRUMENT_REGION_IPP() - - if (dst_data == src_data) - CV_Error(Error::StsBadArg, "Inplace IPP Filter2D is not supported"); - IppiFilterBorder ippiFilterBorder = getIppFunc(src_type); - IppiSize dstRoiSize = { width, height }; - kernel_type borderValue[4] = { 0, 0, 0, 0 }; - IppStatus status = CV_INSTRUMENT_FUN_IPP(ippiFilterBorder, src_data, (int)src_step, dst_data, (int)dst_step, dstRoiSize, ippBorderType, borderValue, spec, buffer); - if (status >= 0) { - CV_IMPL_ADD(CV_IMPL_IPP); - } + IppiFilterBorder ippiFilterBorder = getIppFunc(src_type); + kernel_type borderValue[4] = { 0, 0, 0, 0 }; + status = CV_INSTRUMENT_FUN_IPP(ippiFilterBorder, src_data, (int)src_step, dst_data, (int)dst_step, dstRoiSize, ippBorderType, borderValue, spec, buffer); + if (status >= 0) { + CV_IMPL_ADD(CV_IMPL_IPP); + return true; } -}; + return false; +} #endif -struct DftFilter : public hal::Filter2D +static bool dftFilter2D(int stype, int dtype, int kernel_type, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType) { - 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 sdepth = CV_MAT_DEPTH(stype); @@ -4733,162 +4719,112 @@ struct DftFilter : public hal::Filter2D CV_UNUSED(dtype); int dft_filter_size = 50; #endif - return kernel_width * kernel_height >= dft_filter_size; + if (kernel_width * kernel_height < dft_filter_size) + return false; } - 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; - } + Point anchor = Point(anchor_x, anchor_y); + Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); - 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); - 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) { - // 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 = 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()); - } + Mat src(Size(width, height), stype, src_data, src_step); + Mat dst(Size(width, height), dtype, dst_data, dst_step); + Mat temp; + int src_channels = CV_MAT_CN(stype); + int dst_channels = CV_MAT_CN(dtype); + int ddepth = CV_MAT_DEPTH(dtype); + // 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 = ddepth; + if ((ddepth == CV_32F || ddepth == CV_64F) && src_data != dst_data) { + temp = Mat(Size(width, height), dtype, dst_data, dst_step); } else { - if (src_data != dst_data) - temp = Mat(Size(width, height), dst_type, dst_data, dst_step); - else - 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); + 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()); + } + } else { + if (src_data != dst_data) + temp = Mat(Size(width, height), dtype, dst_data, dst_step); + else + temp.create(Size(width, height), dtype); + crossCorr(src, kernel, temp, src.size(), + CV_MAKETYPE(ddepth, src_channels), + anchor, delta, borderType); + if (temp.data != dst_data) + temp.copyTo(dst); } -}; + return true; +} -struct OcvFilter : public hal::Filter2D +static void ocvFilter2D(int stype, int dtype, int kernel_type, + 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, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType) { - Ptr f; - int src_type; - int dst_type; - bool isIsolated; + int borderTypeValue = borderType & ~BORDER_ISOLATED; + Mat kernel = Mat(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); + Ptr f = createLinearFilter(stype, dtype, kernel, Point(anchor_x, anchor_y), delta, + borderTypeValue); + Mat src(Size(width, height), stype, src_data, src_step); + Mat dst(Size(width, height), dtype, dst_data, dst_step); + f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); +} - 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 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); - f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); - } -}; - - -struct ReplacementSepFilter : public hal::SepFilter2D +static bool replacementSepFilter(int stype, int dtype, int ktype, + 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, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, + int anchor_x, int anchor_y, double delta, int borderType) { cvhalFilter2D *ctx; - bool isInitialized; - ReplacementSepFilter() : ctx(0), isInitialized(false) {} - bool init(int stype, int dtype, int ktype, - uchar * kernelx_data, int kernelx_len, - uchar * kernely_data, int kernely_len, - int anchor_x, int anchor_y, double delta, int borderType) - { - int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, - kernelx_data, kernelx_len, - kernely_data, kernely_len, - anchor_x, anchor_y, delta, borderType); - isInitialized = (res == CV_HAL_ERROR_OK); - return isInitialized; - } - 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) - { - 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"); - } - } - ~ReplacementSepFilter() - { - if (isInitialized) - { - int res = cv_hal_sepFilterFree(ctx); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "Failed to run HAL sepFilter implementation"); - } - } -}; + int res = cv_hal_sepFilterInit(&ctx, stype, dtype, ktype, + kernelx_data, kernelx_len, + kernely_data, kernely_len, + anchor_x, anchor_y, delta, borderType); + if (res != CV_HAL_ERROR_OK) + return false; + res = cv_hal_sepFilter(ctx, src_data, src_step, dst_data, dst_step, width, height, full_width, full_height, offset_x, offset_y); + bool success = (res == CV_HAL_ERROR_OK); + res = cv_hal_sepFilterFree(ctx); + if (res != CV_HAL_ERROR_OK) + return false; + return success; +} -struct OcvSepFilter : public hal::SepFilter2D +static void ocvSepFilter(int stype, int dtype, int ktype, + 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, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, + int anchor_x, int anchor_y, double delta, int borderType) { - Ptr f; - int src_type; - int dst_type; - bool init(int stype, int dtype, int ktype, - uchar * kernelx_data, int kernelx_len, - uchar * kernely_data, int kernely_len, - int anchor_x, int anchor_y, double delta, int borderType) - { - src_type = stype; - dst_type = dtype; - Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data); - Mat kernelY(Size(kernely_len, 1), ktype, kernely_data); - - f = createSeparableLinearFilter( stype, dtype, kernelX, kernelY, - Point(anchor_x, anchor_y), - delta, borderType & ~BORDER_ISOLATED ); - return true; - } - 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); - f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); - } + Mat kernelX(Size(kernelx_len, 1), ktype, kernelx_data); + Mat kernelY(Size(kernely_len, 1), ktype, kernely_data); + Ptr f = createSeparableLinearFilter(stype, dtype, kernelX, kernelY, + Point(anchor_x, anchor_y), + delta, borderType & ~BORDER_ISOLATED); + Mat src(Size(width, height), stype, src_data, src_step); + Mat dst(Size(width, height), dtype, dst_data, dst_step); + f->apply(src, dst, Size(full_width, full_height), Point(offset_x, offset_y)); }; //=================================================================== @@ -4898,97 +4834,124 @@ struct OcvSepFilter : public hal::SepFilter2D namespace cv { namespace hal { -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, - 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)) - { - return Ptr(impl); - } - delete impl; - } +CV_DEPRECATED Ptr Filter2D::create(uchar * , size_t , int , + int , int , + int , int , + int , int , + int , double , + int , int , + bool , bool ) { return Ptr(); } + +CV_DEPRECATED Ptr SepFilter2D::create(int , int , int , + uchar * , int , + uchar * , int , + int , int , + double , int ) { return Ptr(); } + + +void filter2D(int stype, int dtype, int kernel_type, + 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, + uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, + int anchor_x, int anchor_y, + double delta, int borderType, + bool isSubmatrix) +{ + bool res; + res = replacementFilter2D(stype, dtype, kernel_type, + src_data, src_step, + dst_data, dst_step, + width, height, + full_width, full_height, + offset_x, offset_y, + kernel_data, kernel_step, + kernel_width, kernel_height, + anchor_x, anchor_y, + delta, borderType, isSubmatrix); + if (res) + return; #ifdef HAVE_IPP CV_IPP_CHECK() { + res = false; 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)) - { - return Ptr(impl); - } - delete impl; + res = ippFilter2D(stype, dtype, + src_data, src_step, + dst_data, dst_step, + width, height, + kernel_data, kernel_step, + kernel_width, kernel_height, + anchor_x, anchor_y, + delta, borderType, isSubmatrix); } - - 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)) - { - return Ptr(impl); - } - delete impl; + else if (kernel_type == CV_16SC1) { + res = ippFilter2D(stype, dtype, + src_data, src_step, + dst_data, dst_step, + width, height, + kernel_data, kernel_step, + kernel_width, kernel_height, + anchor_x, anchor_y, + delta, borderType, isSubmatrix); } + if (res) + return; } #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)) - { - return Ptr(impl); - } - 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); - return Ptr(impl); - } + res = dftFilter2D(stype, dtype, kernel_type, + src_data, src_step, + dst_data, dst_step, + width, height, + kernel_data, kernel_step, + kernel_width, kernel_height, + anchor_x, anchor_y, + delta, borderType); + if (res) + return; + ocvFilter2D(stype, dtype, kernel_type, + src_data, src_step, + dst_data, dst_step, + width, height, + full_width, full_height, + offset_x, offset_y, + kernel_data, kernel_step, + kernel_width, kernel_height, + anchor_x, anchor_y, + delta, borderType); } //--------------------------------------------------------------- -Ptr SepFilter2D::create(int stype, int dtype, int ktype, - uchar * kernelx_data, int kernelx_len, - uchar * kernely_data, int kernely_len, - int anchor_x, int anchor_y, double delta, int borderType) +void sepFilter2D(int stype, int dtype, int ktype, + 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, + uchar * kernelx_data, int kernelx_len, + uchar * kernely_data, int kernely_len, + int anchor_x, int anchor_y, double delta, int borderType) { - { - ReplacementSepFilter * impl = new ReplacementSepFilter(); - if (impl->init(stype, dtype, ktype, - kernelx_data, kernelx_len, - kernely_data, kernely_len, - anchor_x, anchor_y, delta, borderType)) - { - return Ptr(impl); - } - delete impl; - } - { - OcvSepFilter * impl = new OcvSepFilter(); - impl->init(stype, dtype, ktype, - kernelx_data, kernelx_len, - kernely_data, kernely_len, - anchor_x, anchor_y, delta, borderType); - return Ptr(impl); - } + + bool res = replacementSepFilter(stype, dtype, ktype, + src_data, src_step, dst_data, dst_step, + width, height, full_width, full_height, + offset_x, offset_y, + kernelx_data, kernelx_len, + kernely_data, kernely_len, + anchor_x, anchor_y, delta, borderType); + if (res) + return; + ocvSepFilter(stype, dtype, ktype, + src_data, src_step, dst_data, dst_step, + width, height, full_width, full_height, + offset_x, offset_y, + kernelx_data, kernelx_len, + kernely_data, kernely_len, + anchor_x, anchor_y, delta, borderType); } } // cv::hal:: @@ -5021,10 +4984,12 @@ void cv::filter2D( InputArray _src, OutputArray _dst, int ddepth, if( (borderType & BORDER_ISOLATED) == 0 ) src.locateROI( wsz, ofs ); - 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); + hal::filter2D(src.type(), dst.type(), kernel.type(), + src.data, src.step, dst.data, dst.step, + dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y, + kernel.data, kernel.step, kernel.cols, kernel.rows, + anchor.x, anchor.y, + delta, borderType, src.isSubmatrix()); } void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, @@ -5055,11 +5020,13 @@ void cv::sepFilter2D( InputArray _src, OutputArray _dst, int ddepth, Mat contKernelX = kernelX.isContinuous() ? kernelX : kernelX.clone(); Mat contKernelY = kernelY.isContinuous() ? kernelY : kernelY.clone(); - Ptr c = hal::SepFilter2D::create(src.type(), dst.type(), kernelX.type(), - contKernelX.data, kernelX.cols + kernelX.rows - 1, - contKernelY.data, kernelY.cols + kernelY.rows - 1, - 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); + + hal::sepFilter2D(src.type(), dst.type(), kernelX.type(), + src.data, src.step, dst.data, dst.step, + dst.cols, dst.rows, wsz.width, wsz.height, ofs.x, ofs.y, + contKernelX.data, kernelX.cols + kernelX.rows - 1, + contKernelY.data, kernelY.cols + kernelY.rows - 1, + anchor.x, anchor.y, delta, borderType & ~BORDER_ISOLATED); } diff --git a/modules/imgproc/src/morph.cpp b/modules/imgproc/src/morph.cpp index 52c3411030..4dd0508514 100644 --- a/modules/imgproc/src/morph.cpp +++ b/modules/imgproc/src/morph.cpp @@ -1079,49 +1079,38 @@ namespace cv // ===== 1. replacement implementation -struct ReplacementMorphImpl : public hal::Morph +static bool halMorph(int op, int src_type, int dst_type, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int roi_width, int roi_height, int roi_x, int roi_y, + int roi_width2, int roi_height2, int roi_x2, int roi_y2, + int kernel_type, uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool isSubmatrix) { cvhalFilter2D * ctx; - bool isInitialized; - bool init(int op, int src_type, int dst_type, int max_width, int max_height, - int kernel_type, uchar * kernel_data, size_t kernel_step, int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double borderValue[4], - int iterations, bool isSubmatrix, bool allowInplace) - { - int res = cv_hal_morphInit(&ctx, op, src_type, dst_type, max_width, max_height, - kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, - anchor_x, anchor_y, - borderType, borderValue, - iterations, isSubmatrix, allowInplace); - isInitialized = (res == CV_HAL_ERROR_OK); - return isInitialized; - } - void apply(uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, - int roi_width, int roi_height, int roi_x, int roi_y, - int roi_width2, int roi_height2, int roi_x2, int roi_y2) - { - if (isInitialized) - { - int res = cv_hal_morph(ctx, src_data, src_step, dst_data, dst_step, width, height, - roi_width, roi_height, - roi_x, roi_y, - roi_width2, roi_height2, - roi_x2, roi_y2); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "Failed to run HAL morph implementation"); - } - } - ~ReplacementMorphImpl() - { - if (isInitialized) - { - int res = cv_hal_morphFree(ctx); - if (res != CV_HAL_ERROR_OK) - CV_Error(Error::StsNotImplemented, "Failed to run HAL morph implementation"); - } - } -}; + int res = cv_hal_morphInit(&ctx, op, src_type, dst_type, width, height, + kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, + anchor_x, anchor_y, + borderType, borderValue, + iterations, isSubmatrix, src_data == dst_data); + if (res != CV_HAL_ERROR_OK) + return false; + + res = cv_hal_morph(ctx, src_data, src_step, dst_data, dst_step, width, height, + roi_width, roi_height, + roi_x, roi_y, + roi_width2, roi_height2, + roi_x2, roi_y2); + bool success = (res == CV_HAL_ERROR_OK); + + res = cv_hal_morphFree(ctx); + if (res != CV_HAL_ERROR_OK) + return false; + + return success; +} // ===== 2. IPP implementation @@ -1133,7 +1122,7 @@ template struct IppMorphTrait {}; #if IPP_VERSION_X100 >= 900 -#define INIT_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ +#define DEFINE_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ template <>\ struct IppMorphTrait\ {\ @@ -1153,7 +1142,7 @@ struct IppMorphTrait\ #else -#define INIT_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ +#define DEFINE_TRAIT(cvtype, ipptype, flavor, channels, zerodef)\ template <>\ struct IppMorphTrait\ {\ @@ -1173,28 +1162,28 @@ struct IppMorphTrait\ #endif -INIT_TRAIT(CV_8UC1, 8u, 8u_C1R, 1, zero = 0) -INIT_TRAIT(CV_8UC3, 8u, 8u_C3R, 3, zero[3] = {0}) -INIT_TRAIT(CV_8UC4, 8u, 8u_C4R, 4, zero[4] = {0}) -INIT_TRAIT(CV_32FC1, 32f, 32f_C1R, 1, zero = 0) -INIT_TRAIT(CV_32FC3, 32f, 32f_C3R, 3, zero[3] = {0}) -INIT_TRAIT(CV_32FC4, 32f, 32f_C4R, 4, zero[4] = {0}) +DEFINE_TRAIT(CV_8UC1, 8u, 8u_C1R, 1, zero = 0) +DEFINE_TRAIT(CV_8UC3, 8u, 8u_C3R, 3, zero[3] = {0}) +DEFINE_TRAIT(CV_8UC4, 8u, 8u_C4R, 4, zero[4] = {0}) +DEFINE_TRAIT(CV_32FC1, 32f, 32f_C1R, 1, zero = 0) +DEFINE_TRAIT(CV_32FC3, 32f, 32f_C3R, 3, zero[3] = {0}) +DEFINE_TRAIT(CV_32FC4, 32f, 32f_C4R, 4, zero[4] = {0}) -#undef INIT_TRAIT +#undef DEFINE_TRAIT //-------------------------------------- -struct IppMorphBaseImpl : public hal::Morph -{ - virtual bool init(int _op, int _src_type, int dst_type, int max_width, int max_height, - int kernel_type, uchar * kernel_data, size_t kernel_step, int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double borderValue[4], - int iterations, bool isSubmatrix, bool allowInplace) = 0; -}; template -struct IppMorphImpl : public IppMorphBaseImpl +static bool ippMorph(int op, int src_type, int dst_type, + const uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int roi_width, int roi_height, int roi_x, int roi_y, + int roi_width2, int roi_height2, int roi_x2, int roi_y2, + int kernel_type, uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool isSubmatrix) { IppMorphTrait trait; typedef typename IppMorphTrait::ipp_data_type ipp_data_type; @@ -1203,177 +1192,136 @@ struct IppMorphImpl : public IppMorphBaseImpl IppiSize kernelSize; bool rectKernel; IppiPoint anchor; - int op; - int src_type; - int border; - bool init(int _op, int _src_type, int dst_type, int max_width, int max_height, - int kernel_type, uchar * kernel_data, size_t kernel_step, int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double borderValue[4], - int iterations, bool isSubmatrix, bool allowInplace) + CV_INSTRUMENT_REGION_IPP() + + CV_UNUSED(roi_width); CV_UNUSED(roi_height); CV_UNUSED(roi_x); CV_UNUSED(roi_y); + CV_UNUSED(roi_width2); CV_UNUSED(roi_height2); CV_UNUSED(roi_x2); CV_UNUSED(roi_y2); + CV_UNUSED(dst_type); + + anchor = ippiPoint(anchor_x, anchor_y); + + Mat kernel(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); + int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); + + if( !( depth == CV_8U || depth == CV_32F ) + || !(cn == 1 || cn == 3 || cn == 4) + || !( borderType == cv::BORDER_REPLICATE + || (borderType == cv::BORDER_CONSTANT && Vec(borderValue) == morphologyDefaultBorderValue() && kernel.size() == Size(3,3))) + || !( op == MORPH_DILATE || op == MORPH_ERODE) + || isSubmatrix + || src_data == dst_data) + return false; + + // In case BORDER_CONSTANT, IPPMorphReplicate works correct with kernels of size 3*3 only + if( borderType == cv::BORDER_CONSTANT && kernel.data ) { - border = borderType; // TODO: remove - anchor = ippiPoint(anchor_x, anchor_y); - CV_UNUSED(dst_type); - src_type = _src_type; - - Mat kernel(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); - int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); - - if( !( depth == CV_8U || depth == CV_32F ) - || !(cn == 1 || cn == 3 || cn == 4) - || !( borderType == cv::BORDER_REPLICATE - || (borderType == cv::BORDER_CONSTANT && Vec(borderValue) == morphologyDefaultBorderValue() && kernel.size() == Size(3,3))) - || !( op == MORPH_DILATE || op == MORPH_ERODE) - || isSubmatrix - || allowInplace) - return false; - - // In case BORDER_CONSTANT, IPPMorphReplicate works correct with kernels of size 3*3 only - if( borderType == cv::BORDER_CONSTANT && kernel.data ) + int x, y; + for( y = 0; y < kernel.rows; y++ ) { - int x, y; - for( y = 0; y < kernel.rows; y++ ) - { - if( kernel.at(y, anchor.x) != 0 ) - continue; - for( x = 0; x < kernel.cols; x++ ) - { - if( kernel.at(y,x) != 0 ) - return false; - } - } + if( kernel.at(y, anchor.x) != 0 ) + continue; for( x = 0; x < kernel.cols; x++ ) { - if( kernel.at(anchor.y, x) != 0 ) - continue; - for( y = 0; y < kernel.rows; y++ ) - { - if( kernel.at(y,x) != 0 ) - return false; - } + if( kernel.at(y,x) != 0 ) + return false; } - } - - Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); - - rectKernel = false; - if( kernel.empty() ) + for( x = 0; x < kernel.cols; x++ ) { - ksize = Size(1+iterations*2,1+iterations*2); - anchor = ippiPoint(iterations, iterations); - rectKernel = true; - iterations = 1; - } - else if( iterations >= 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) - { - ksize = Size(ksize.width + (iterations-1)*(ksize.width-1), - ksize.height + (iterations-1)*(ksize.height-1)), - anchor = ippiPoint(anchor.x*iterations, anchor.y*iterations); - kernel = Mat(); - rectKernel = true; - iterations = 1; - } - - // TODO: implement the case of iterations > 1. - if( iterations > 1 ) - return false; - - IppiSize roiSize = {max_width, max_height}; - kernelSize = ippiSize(ksize); - op = _op; - - IppStatus res; - if (!rectKernel) - { - if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) - return false; - int specSize = 0, bufferSize = 0; - res = trait.getMorphSize(roiSize, kernelSize, &specSize, &bufferSize); - if (res >= 0) + if( kernel.at(anchor.y, x) != 0 ) + continue; + for( y = 0; y < kernel.rows; y++ ) { - specBuf.Alloc(specSize); - workBuf.Alloc(bufferSize); - res = trait.morphInit(roiSize, kernel.ptr(), kernelSize, specBuf, workBuf); - if (res >= 0) - return true; - } - } - else - { - if (((kernelSize.width - 1) / 2 != anchor.x) || ((kernelSize.height - 1) / 2 != anchor.y)) - return false; - if (op == MORPH_ERODE) - { - int bufSize = 0; - res = trait.filterGetMinSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); - if (res >= 0) - { - workBuf.Alloc(bufSize); - return true; - } - } - else - { - int bufSize = 0; - res = trait.filterGetMaxSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); - if (res >= 0) - { - workBuf.Alloc(bufSize); - return true; - } + if( kernel.at(y,x) != 0 ) + return false; } } + + } + + Size ksize = !kernel.empty() ? kernel.size() : Size(3,3); + + rectKernel = false; + if( kernel.empty() ) + { + ksize = Size(1+iterations*2,1+iterations*2); + anchor = ippiPoint(iterations, iterations); + rectKernel = true; + iterations = 1; + } + else if( iterations >= 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) + { + ksize = Size(ksize.width + (iterations-1)*(ksize.width-1), + ksize.height + (iterations-1)*(ksize.height-1)), + anchor = ippiPoint(anchor.x*iterations, anchor.y*iterations); + kernel = Mat(); + rectKernel = true; + iterations = 1; + } + + // TODO: implement the case of iterations > 1. + if( iterations > 1 ) return false; - } - void apply(uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, - int roi_width, int roi_height, int roi_x, int roi_y, - int roi_width2, int roi_height2, int roi_x2, int roi_y2) + IppiSize roiSize = {width, height}; + kernelSize = ippiSize(ksize); + + IppStatus res; + if (!rectKernel) { - CV_INSTRUMENT_REGION_IPP() - - CV_UNUSED(roi_width); CV_UNUSED(roi_height); CV_UNUSED(roi_x); CV_UNUSED(roi_y); - CV_UNUSED(roi_width2); CV_UNUSED(roi_height2); CV_UNUSED(roi_x2); CV_UNUSED(roi_y2); - if (src_data == dst_data) - CV_Error(Error::StsBadArg, "IPP Morph inplace is not alowed"); - - IppiSize roiSize = {width, height}; - - IppStatus res; - if (!rectKernel) + if (((kernel.cols - 1) / 2 != anchor.x) || ((kernel.rows - 1) / 2 != anchor.y)) + return false; + int specSize = 0, bufferSize = 0; + res = trait.getMorphSize(roiSize, kernelSize, &specSize, &bufferSize); + if (res >= 0) { - if (op == MORPH_ERODE) - res = (trait.morphErode((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); + specBuf.Alloc(specSize); + workBuf.Alloc(bufferSize); + res = trait.morphInit(roiSize, kernel.ptr(), kernelSize, specBuf, workBuf); + if (res < 0) + return false; + } + } + else + { + if (((kernelSize.width - 1) / 2 != anchor.x) || ((kernelSize.height - 1) / 2 != anchor.y)) + return false; + if (op == MORPH_ERODE) + { + int bufSize = 0; + res = trait.filterGetMinSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); + if (res >= 0) + workBuf.Alloc(bufSize); else - res = (trait.morphDilate((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); + return false; } else { - if (op == MORPH_ERODE) - res = (trait.filterMinBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); + int bufSize = 0; + res = trait.filterGetMaxSize(roiSize, kernelSize, trait.getDataType(), trait.cn, &bufSize); + if (res >= 0) + workBuf.Alloc(bufSize); else - res = (trait.filterMaxBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); + return false; } - if (res < 0) - CV_Error(Error::StsBadArg, "Failed to run IPP morph"); } -}; -static IppMorphBaseImpl * createIppImpl(int type) -{ - switch (type) + if (!rectKernel) { - case CV_8UC1: return new IppMorphImpl(); - case CV_8UC3: return new IppMorphImpl(); - case CV_8UC4: return new IppMorphImpl(); - case CV_32FC1: return new IppMorphImpl(); - case CV_32FC3: return new IppMorphImpl(); - case CV_32FC4: return new IppMorphImpl(); + if (op == MORPH_ERODE) + res = (trait.morphErode((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); + else + res = (trait.morphDilate((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, specBuf, workBuf)); } - return 0; + else + { + if (op == MORPH_ERODE) + res = (trait.filterMinBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); + else + res = (trait.filterMaxBorder((ipp_data_type*)src_data, (int)src_step, (ipp_data_type*)dst_data, (int)dst_step, roiSize, kernelSize, anchor, workBuf)); + } + return res >= 0; } #endif // IPP_VERSION_X100 >= 810 @@ -1381,94 +1329,108 @@ static IppMorphBaseImpl * createIppImpl(int type) // ===== 3. Fallback implementation -struct OcvMorphImpl : public hal::Morph +static void ocvMorph(int op, int src_type, int dst_type, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int roi_width, int roi_height, int roi_x, int roi_y, + int roi_width2, int roi_height2, int roi_x2, int roi_y2, + int kernel_type, uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations) { - Ptr f; - int iterations; - int src_type; - int dst_type; - bool init(int op, int _src_type, int _dst_type, int, int, - int kernel_type, uchar * kernel_data, size_t kernel_step, int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double _borderValue[4], - int _iterations, bool, bool) + Mat kernel(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); + Point anchor(anchor_x, anchor_y); + Vec borderVal(borderValue); + Ptr f = createMorphologyFilter(op, src_type, kernel, anchor, borderType, borderType, borderVal); + Mat src(Size(width, height), src_type, src_data, src_step); + Mat dst(Size(width, height), dst_type, dst_data, dst_step); { - iterations = _iterations; - src_type = _src_type; - dst_type = _dst_type; - Mat kernel(Size(kernel_width, kernel_height), kernel_type, kernel_data, kernel_step); - Point anchor(anchor_x, anchor_y); - Vec borderValue(_borderValue); - f = createMorphologyFilter(op, src_type, kernel, anchor, borderType, borderType, borderValue ); - return true; + Point ofs(roi_x, roi_y); + Size wsz(roi_width, roi_height); + f->apply( src, dst, wsz, ofs ); } + { + Point ofs(roi_x2, roi_y2); + Size wsz(roi_width2, roi_height2); + for( int i = 1; i < iterations; i++ ) + f->apply( dst, dst, wsz, ofs ); + } +} - void apply(uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height, - int roi_width, int roi_height, int roi_x, int roi_y, - int roi_width2, int roi_height2, int roi_x2, int roi_y2) - { - Mat src(Size(width, height), src_type, src_data, src_step); - Mat dst(Size(width, height), dst_type, dst_data, dst_step); - { - Point ofs(roi_x, roi_y); - Size wsz(roi_width, roi_height); - f->apply( src, dst, wsz, ofs ); - } - { - Point ofs(roi_x2, roi_y2); - Size wsz(roi_width2, roi_height2); - for( int i = 1; i < iterations; i++ ) - f->apply( dst, dst, wsz, ofs ); - } - } -}; // ===== HAL interface implementation namespace hal { -Ptr Morph ::create(int op, int src_type, int dst_type, int max_width, int max_height, - int kernel_type, uchar * kernel_data, size_t kernel_step, int kernel_width, int kernel_height, - int anchor_x, int anchor_y, - int borderType, const double borderValue[4], - int iterations, bool isSubmatrix, bool allowInplace) + +CV_DEPRECATED Ptr Morph::create(int , int , int , int , int , + int , uchar * , size_t , + int , int , + int , int , + int , const double *, + int , bool , bool ) { return Ptr(); } + + +void morph(int op, int src_type, int dst_type, + uchar * src_data, size_t src_step, + uchar * dst_data, size_t dst_step, + int width, int height, + int roi_width, int roi_height, int roi_x, int roi_y, + int roi_width2, int roi_height2, int roi_x2, int roi_y2, + int kernel_type, uchar * kernel_data, size_t kernel_step, + int kernel_width, int kernel_height, int anchor_x, int anchor_y, + int borderType, const double borderValue[4], int iterations, bool isSubmatrix) { { - ReplacementMorphImpl * impl = new ReplacementMorphImpl(); - if (impl->init(op, src_type, dst_type, max_width, max_height, - kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, - anchor_x, anchor_y, - borderType, borderValue, iterations, isSubmatrix, allowInplace)) - { - return Ptr(impl); - } - delete impl; + bool res = halMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, + roi_width, roi_height, roi_x, roi_y, + roi_width2, roi_height2, roi_x2, roi_y2, + kernel_type, kernel_data, kernel_step, + kernel_width, kernel_height, anchor_x, anchor_y, + borderType, borderValue, iterations, isSubmatrix); + if (res) + return; } + #if defined(HAVE_IPP) && IPP_VERSION_X100 >= 810 + +#define ONE_CASE(type) \ + case type: \ + res = ippMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, \ + roi_width, roi_height, roi_x, roi_y, \ + roi_width2, roi_height2, roi_x2, roi_y2, \ + kernel_type, kernel_data, kernel_step, \ + kernel_width, kernel_height, anchor_x, anchor_y, \ + borderType, borderValue, iterations, isSubmatrix); \ + break; + CV_IPP_CHECK() { - IppMorphBaseImpl * impl = createIppImpl(src_type); - if (impl) + bool res = false; + switch (src_type) { - if (impl->init(op, src_type, dst_type, max_width, max_height, - kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, - anchor_x, anchor_y, - borderType, borderValue, iterations, isSubmatrix, allowInplace)) - { - return Ptr(impl); - } - delete impl; + ONE_CASE(CV_8UC1) + ONE_CASE(CV_8UC3) + ONE_CASE(CV_8UC4) + ONE_CASE(CV_32FC1) + ONE_CASE(CV_32FC3) + ONE_CASE(CV_32FC4) } + if (res) + return; } + +#undef ONE_CASE + #endif - { - OcvMorphImpl * impl = new OcvMorphImpl(); - impl->init(op, src_type, dst_type, max_width, max_height, - kernel_type, kernel_data, kernel_step, kernel_width, kernel_height, - anchor_x, anchor_y, - borderType, borderValue, iterations, isSubmatrix, allowInplace); - return Ptr(impl); - } + + ocvMorph(op, src_type, dst_type, src_data, src_step, dst_data, dst_step, width, height, + roi_width, roi_height, roi_x, roi_y, + roi_width2, roi_height2, roi_x2, roi_y2, + kernel_type, kernel_data, kernel_step, + kernel_width, kernel_height, anchor_x, anchor_y, + borderType, borderValue, iterations); } } // cv::hal @@ -1941,13 +1903,15 @@ static void morphOp( int op, InputArray _src, OutputArray _dst, dst.locateROI(d_wsz, d_ofs); } - Ptr ctx = hal::Morph::create(op, src.type(), dst.type(), src.cols, src.rows, - kernel.type(), kernel.data, kernel.step, kernel.cols, kernel.rows, - anchor.x, anchor.y, borderType, borderValue.val, iterations, - (src.isSubmatrix() && !isolated), src.data == dst.data); - ctx->apply(src.data, src.step, dst.data, dst.step, src.cols, src.rows, + hal::morph(op, src.type(), dst.type(), + src.data, src.step, + dst.data, dst.step, + src.cols, src.rows, s_wsz.width, s_wsz.height, s_ofs.x, s_ofs.y, - d_wsz.width, d_wsz.height, d_ofs.x, d_ofs.y); + d_wsz.width, d_wsz.height, d_ofs.x, d_ofs.y, + kernel.type(), kernel.data, kernel.step, kernel.cols, kernel.rows, anchor.x, anchor.y, + borderType, borderValue.val, iterations, + (src.isSubmatrix() && !isolated)); } }