mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #29427 from Akansha-977:filter2D_IPP_migration_4.x
Filter2D IPP migration to HAL for 4.x #29427 ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
@@ -21,6 +21,7 @@ add_library(ipphal STATIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/box_filter_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp"
|
||||
)
|
||||
|
||||
#TODO: HAVE_IPP_ICV and HAVE_IPP_IW added as private macro till OpenCV itself is
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
// Disabled in https://github.com/opencv/opencv/pull/13085 due large binary size
|
||||
#define DISABLE_IPP_BOX_FILTER 1
|
||||
|
||||
// IPP filter2D integration is disabled in main OpenCV; kept behind a macro like box filter
|
||||
#define DISABLE_IPP_FILTER2D 1
|
||||
// Too big difference compared to OpenCV FFT-based convolution, different results on masks > 7x7
|
||||
#define IPP_DISABLE_FILTER2D_BIG_MASK 1
|
||||
|
||||
#if IPP_VERSION_X100 >= 810
|
||||
#if defined(HAVE_IPP_IW)
|
||||
int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int src_width, int src_height, uchar *dst_data, size_t dst_step, int dst_width,
|
||||
@@ -68,6 +73,19 @@ int ipp_hal_remap32f(int src_type, const uchar *src_data, size_t src_step, int s
|
||||
#undef cv_hal_remap32f
|
||||
#define cv_hal_remap32f ipp_hal_remap32f
|
||||
|
||||
#if defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
int ipp_hal_filter2D(const uchar * src_data, size_t src_step, int src_type,
|
||||
uchar * dst_data, size_t dst_step, int dst_type,
|
||||
int width, int height, int full_width, int full_height,
|
||||
int offset_x, int offset_y,
|
||||
const uchar * kernel_data, size_t kernel_step, int kernel_type,
|
||||
int kernel_width, int kernel_height,
|
||||
int anchor_x, int anchor_y, double delta, int borderType,
|
||||
bool isSubmatrix, bool allowInplace);
|
||||
#undef cv_hal_filter_stateless
|
||||
#define cv_hal_filter_stateless ipp_hal_filter2D
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
|
||||
#endif //IPP_VERSION_X100 >= 810
|
||||
|
||||
#if IPP_VERSION_X100 >= 700
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
// This file is part of OpenCV project.
|
||||
// It is subject to the license terms in the LICENSE file found in the top-level directory
|
||||
// of this distribution and at http://opencv.org/license.html
|
||||
// Copyright (C) 2026, BigVision LLC, all rights reserved.
|
||||
// Third party copyrights are property of their respective owners.
|
||||
|
||||
#include "ipp_hal_imgproc.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include "precomp_ipp.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cfloat>
|
||||
|
||||
#if defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
|
||||
// Copied from core/private.hpp (gated by HAVE_IPP, which the plugin lacks).
|
||||
// filterGetIppBorderType: distinct name; adds the BORDER_REFLECT_101 -> ippBorderMirror
|
||||
// case that precomp_ipp.hpp's ippiGetBorderType omits.
|
||||
static inline IppiBorderType filterGetIppBorderType(int borderTypeNI)
|
||||
{
|
||||
return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst :
|
||||
borderTypeNI == cv::BORDER_TRANSPARENT ? ippBorderTransp :
|
||||
borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl :
|
||||
borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror :
|
||||
(IppiBorderType)-1;
|
||||
}
|
||||
|
||||
static inline bool ippiCheckAnchor(int x, int y, int kernelWidth, int kernelHeight)
|
||||
{
|
||||
return (x == (kernelWidth - 1)/2 && y == (kernelHeight - 1)/2);
|
||||
}
|
||||
|
||||
static inline IppiBorderType ippiGetBorder(::ipp::IwiImage &image, int ocvBorderType, ::ipp::IwiBorderSize &borderSize)
|
||||
{
|
||||
int inMemFlags = 0;
|
||||
IppiBorderType border = filterGetIppBorderType(ocvBorderType & ~cv::BORDER_ISOLATED);
|
||||
if((int)border == -1)
|
||||
return (IppiBorderType)0;
|
||||
|
||||
if(!(ocvBorderType & cv::BORDER_ISOLATED))
|
||||
{
|
||||
if(image.m_inMemSize.left)
|
||||
{
|
||||
if(image.m_inMemSize.left >= borderSize.left)
|
||||
inMemFlags |= ippBorderInMemLeft;
|
||||
else
|
||||
return (IppiBorderType)0;
|
||||
}
|
||||
else
|
||||
borderSize.left = 0;
|
||||
if(image.m_inMemSize.top)
|
||||
{
|
||||
if(image.m_inMemSize.top >= borderSize.top)
|
||||
inMemFlags |= ippBorderInMemTop;
|
||||
else
|
||||
return (IppiBorderType)0;
|
||||
}
|
||||
else
|
||||
borderSize.top = 0;
|
||||
if(image.m_inMemSize.right)
|
||||
{
|
||||
if(image.m_inMemSize.right >= borderSize.right)
|
||||
inMemFlags |= ippBorderInMemRight;
|
||||
else
|
||||
return (IppiBorderType)0;
|
||||
}
|
||||
else
|
||||
borderSize.right = 0;
|
||||
if(image.m_inMemSize.bottom)
|
||||
{
|
||||
if(image.m_inMemSize.bottom >= borderSize.bottom)
|
||||
inMemFlags |= ippBorderInMemBottom;
|
||||
else
|
||||
return (IppiBorderType)0;
|
||||
}
|
||||
else
|
||||
borderSize.bottom = 0;
|
||||
}
|
||||
else
|
||||
borderSize.left = borderSize.right = borderSize.top = borderSize.bottom = 0;
|
||||
|
||||
return (IppiBorderType)(border | inMemFlags);
|
||||
}
|
||||
|
||||
int ipp_hal_filter2D(const uchar * src_data, size_t src_step, int src_type,
|
||||
uchar * dst_data, size_t dst_step, int dst_type,
|
||||
int width, int height, int full_width, int full_height,
|
||||
int offset_x, int offset_y,
|
||||
const uchar * kernel_data, size_t kernel_step, int kernel_type,
|
||||
int kernel_width, int kernel_height,
|
||||
int anchor_x, int anchor_y, double delta, int borderType,
|
||||
bool isSubmatrix, bool allowInplace)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
IppDataType type = ippiGetDataType(CV_MAT_DEPTH(src_type));
|
||||
int channels = CV_MAT_CN(src_type);
|
||||
|
||||
CV_UNUSED(isSubmatrix);
|
||||
CV_UNUSED(allowInplace);
|
||||
|
||||
#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel
|
||||
if(kernel_width == 1 && kernel_height == 1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
#if IPP_DISABLE_FILTER2D_BIG_MASK
|
||||
// Too big difference compared to OpenCV FFT-based convolution
|
||||
if(kernel_type == CV_32FC1 && (type == ipp16s || type == ipp16u) && (kernel_width > 7 || kernel_height > 7))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Poor optimization for big kernels
|
||||
if(kernel_width > 7 || kernel_height > 7)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
if(src_data == dst_data)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(src_type != dst_type)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(kernel_type != CV_16SC1 && kernel_type != CV_32FC1)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// TODO: Implement offset for 8u, 16u
|
||||
if(std::fabs(delta) >= DBL_EPSILON)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(!ippiCheckAnchor(anchor_x, anchor_y, kernel_width, kernel_height))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiSize iwSize(width, height);
|
||||
::ipp::IwiSize kernelSize(kernel_width, kernel_height);
|
||||
::ipp::IwiImage iwKernel(ippiSize(kernel_width, kernel_height), ippiGetDataType(CV_MAT_DEPTH(kernel_type)), CV_MAT_CN(kernel_type), 0, (void*)kernel_data, kernel_step);
|
||||
::ipp::IwiImage iwSrc(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)src_data, src_step);
|
||||
::ipp::IwiImage iwDst(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)dst_data, dst_step);
|
||||
|
||||
::ipp::IwiBorderSize iwBorderSize = ::ipp::iwiSizeToBorderSize(kernelSize);
|
||||
::ipp::IwiBorderType iwBorderType = ippiGetBorder(iwSrc, borderType, iwBorderSize);
|
||||
if(!iwBorderType)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilter, iwSrc, iwDst, iwKernel, ::ipp::IwiFilterParams(1, 0, ippAlgHintNone, ippRndFinancial), iwBorderType);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_FILTER2D
|
||||
@@ -1227,93 +1227,6 @@ static bool replacementFilter2D(int stype, int dtype, int kernel_type,
|
||||
return success;
|
||||
}
|
||||
|
||||
#if 0 //defined HAVE_IPP
|
||||
static bool ippFilter2D(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)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
::ipp::IwiSize iwSize(width, height);
|
||||
::ipp::IwiSize kernelSize(kernel_width, kernel_height);
|
||||
IppDataType type = ippiGetDataType(CV_MAT_DEPTH(stype));
|
||||
int channels = CV_MAT_CN(stype);
|
||||
|
||||
CV_UNUSED(isSubmatrix);
|
||||
|
||||
#if IPP_VERSION_X100 >= 201700 && IPP_VERSION_X100 <= 201702 // IPP bug with 1x1 kernel
|
||||
if(kernel_width == 1 && kernel_height == 1)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if IPP_DISABLE_FILTER2D_BIG_MASK
|
||||
// Too big difference compared to OpenCV FFT-based convolution
|
||||
if(kernel_type == CV_32FC1 && (type == ipp16s || type == ipp16u) && (kernel_width > 7 || kernel_height > 7))
|
||||
return false;
|
||||
|
||||
// Poor optimization for big kernels
|
||||
if(kernel_width > 7 || kernel_height > 7)
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if(src_data == dst_data)
|
||||
return false;
|
||||
|
||||
if(stype != dtype)
|
||||
return false;
|
||||
|
||||
if(kernel_type != CV_16SC1 && kernel_type != CV_32FC1)
|
||||
return false;
|
||||
|
||||
// TODO: Implement offset for 8u, 16u
|
||||
if(std::fabs(delta) >= DBL_EPSILON)
|
||||
return false;
|
||||
|
||||
if(!ippiCheckAnchor(anchor_x, anchor_y, kernel_width, kernel_height))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiBorderSize iwBorderSize;
|
||||
::ipp::IwiBorderType iwBorderType;
|
||||
::ipp::IwiImage iwKernel(ippiSize(kernel_width, kernel_height), ippiGetDataType(CV_MAT_DEPTH(kernel_type)), CV_MAT_CN(kernel_type), 0, (void*)kernel_data, kernel_step);
|
||||
::ipp::IwiImage iwSrc(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)src_data, src_step);
|
||||
::ipp::IwiImage iwDst(iwSize, type, channels, ::ipp::IwiBorderSize(offset_x, offset_y, full_width-offset_x-width, full_height-offset_y-height), (void*)dst_data, dst_step);
|
||||
|
||||
iwBorderSize = ::ipp::iwiSizeToBorderSize(kernelSize);
|
||||
iwBorderType = ippiGetBorder(iwSrc, borderType, iwBorderSize);
|
||||
if(!iwBorderType)
|
||||
return false;
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilter, iwSrc, iwDst, iwKernel, ::ipp::IwiFilterParams(1, 0, ippAlgHintNone, ippRndFinancial), iwBorderType);
|
||||
}
|
||||
catch(const ::ipp::IwException& ex)
|
||||
{
|
||||
CV_UNUSED(ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(stype); CV_UNUSED(dtype); CV_UNUSED(kernel_type); CV_UNUSED(src_data); CV_UNUSED(src_step);
|
||||
CV_UNUSED(dst_data); CV_UNUSED(dst_step); CV_UNUSED(width); CV_UNUSED(height); CV_UNUSED(full_width);
|
||||
CV_UNUSED(full_height); CV_UNUSED(offset_x); CV_UNUSED(offset_y); CV_UNUSED(kernel_data); CV_UNUSED(kernel_step);
|
||||
CV_UNUSED(kernel_width); CV_UNUSED(kernel_height); CV_UNUSED(anchor_x); CV_UNUSED(anchor_y); CV_UNUSED(delta);
|
||||
CV_UNUSED(borderType); CV_UNUSED(isSubmatrix);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool dftFilter2D(int stype, int dtype, int kernel_type,
|
||||
uchar * src_data, size_t src_step,
|
||||
uchar * dst_data, size_t dst_step,
|
||||
@@ -1524,17 +1437,6 @@ void filter2D(int stype, int dtype, int kernel_type,
|
||||
if (res)
|
||||
return;
|
||||
|
||||
/*CV_IPP_RUN_FAST(ippFilter2D(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))*/
|
||||
|
||||
res = dftFilter2D(stype, dtype, kernel_type,
|
||||
src_data, src_step,
|
||||
dst_data, dst_step,
|
||||
|
||||
Reference in New Issue
Block a user