1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-21 19:33:03 +04:00

moved ipp deriv to hal

This commit is contained in:
Fedorov, Andrey
2026-07-01 02:13:48 -07:00
parent 5b83b0c440
commit 2f779c5c36
4 changed files with 261 additions and 101 deletions
+1
View File
@@ -16,6 +16,7 @@ add_library(ipphal STATIC
"${CMAKE_CURRENT_SOURCE_DIR}/src/cart_polar_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/transforms_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/warp_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/deriv_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/resize_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp"
+15
View File
@@ -15,6 +15,21 @@ int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int
int dst_height, const double M[6], int interpolation, int borderType, const double borderValue[4]);
#undef cv_hal_warpAffine
#define cv_hal_warpAffine ipp_hal_warpAffine
int ipp_hal_sobel(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
int width, int height, int src_depth, int dst_depth, int cn,
int margin_left, int margin_top, int margin_right, int margin_bottom,
int dx, int dy, int ksize, double scale, double delta, int border_type);
#undef cv_hal_sobel
#define cv_hal_sobel ipp_hal_sobel
int ipp_hal_scharr(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
int width, int height, int src_depth, int dst_depth, int cn,
int margin_left, int margin_top, int margin_right, int margin_bottom,
int dx, int dy, double scale, double delta, int border_type);
#undef cv_hal_scharr
#define cv_hal_scharr ipp_hal_scharr
#endif
#if IPP_VERSION_X100 >= 202600
+245
View File
@@ -0,0 +1,245 @@
// 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, Intel Corporation, all rights reserved.
#include "ipp_hal_imgproc.hpp"
#include "precomp_ipp.hpp"
#include <opencv2/core.hpp>
#include <opencv2/core/base.hpp>
#if IPP_VERSION_X100 >= 810
#ifdef HAVE_IPP_IW
#include "iw++/iw.hpp"
static inline IppiMaskSize ippiGetMaskSize(int kx, int ky)
{
return (kx == 1 && ky == 3) ? ippMskSize1x3 :
(kx == 1 && ky == 5) ? ippMskSize1x5 :
(kx == 3 && ky == 1) ? ippMskSize3x1 :
(kx == 3 && ky == 3) ? ippMskSize3x3 :
(kx == 5 && ky == 1) ? ippMskSize5x1 :
(kx == 5 && ky == 5) ? ippMskSize5x5 :
(IppiMaskSize)-1;
}
static inline IwiDerivativeType ippiGetDerivType(int dx, int dy, bool nvert)
{
return (dx == 1 && dy == 0) ? ((nvert)?iwiDerivNVerFirst:iwiDerivVerFirst) :
(dx == 0 && dy == 1) ? iwiDerivHorFirst :
(dx == 2 && dy == 0) ? iwiDerivVerSecond :
(dx == 0 && dy == 2) ? iwiDerivHorSecond :
(IwiDerivativeType)-1;
}
// Build an IwiImage from a raw buffer, encoding the in-memory border (the OpenCV
// margins around the ROI) so that BORDER_*-with-physical-pixels works as in core.
// TODO: promote to precomp_ipp.hpp and unify with the raw-pointer ippiGetImage in
// transforms_ipp.cpp once more filter HALs share it
static inline ::ipp::IwiImage ippiGetImage(int depth, int channels, const uchar* data, size_t step,
int width, int height,
int margin_left, int margin_top, int margin_right, int margin_bottom)
{
::ipp::IwiImage image;
::ipp::IwiBorderSize inMemBorder((IwSize)margin_left, (IwSize)margin_top, (IwSize)margin_right, (IwSize)margin_bottom);
image.Init({width, height}, ippiGetDataType(depth), channels, inMemBorder, (void*)data, step);
return image;
}
// Translate the OpenCV border type into an IPP border, accounting for in-memory pixels.
// Returns (IppiBorderType)0 on unsupported configuration.
// TODO: promote to precomp_ipp.hpp once shared by other filter HALs (box/gaussian/bilateral/
// sepFilter etc.). Note the shared ippiGetBorderType there does not map BORDER_REFLECT_101;
// widening it would also affect warp_ipp.cpp, so keep this filter-specific mapping separate
// (or add a dedicated filter border helper) when consolidating.
static inline IppiBorderType ippiGetBorder(::ipp::IwiImage &image, int ocvBorderType, ::ipp::IwiBorderSize &borderSize)
{
int inMemFlags = 0;
int borderTypeNI = ocvBorderType & ~cv::BORDER_ISOLATED;
IppiBorderType border = borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst :
borderTypeNI == cv::BORDER_TRANSPARENT ? ippBorderTransp :
borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl :
borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror :
(IppiBorderType)-1;
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);
}
// Shared worker for Sobel (useScharr == false) and Scharr (useScharr == true).
static int ipp_Deriv(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
int width, int height, int src_depth, int dst_depth, int cn,
int margin_left, int margin_top, int margin_right, int margin_bottom,
int dx, int dy, int ksize, double scale, double delta, int borderType,
bool useScharr)
{
IppDataType srcType = ippiGetDataType(src_depth);
IppDataType dstType = ippiGetDataType(dst_depth);
bool useScale = false;
if(cn < 1 || cn > 4)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if(src_depth < 0 || src_depth >= CV_DEPTH_MAX || dst_depth < 0 || dst_depth >= CV_DEPTH_MAX)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
// Supported (source depth -> destination depth) x channels combinations.
// Index order: [src_depth][dst_depth][channel-1]; depths are 8U,8S,16U,16S,32S,32F,64F.
// IPP iwiFilterSobel/iwiFilterScharr provide only single-channel kernels for
// 8u->16s, 16s->16s and 32f->32f; 8u->8u is realized as an 8u->16s filter plus a 16s->8u scale.
// 8u->32f and 16s->32f are intentionally left disabled: IPP would need an extra full-image
// conversion pass there and is slower than OpenCV's fused sepFilter2D.
/* dst: 8U 8S 16U 16S 32S 32F 64F */
#if defined(IPP_CALLS_ENFORCED)
const char impl[CV_DEPTH_MAX][CV_DEPTH_MAX][4] = {
/* src 8U */ {{1,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 8S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 16U */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 16S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 32S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 32F */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0}},
/* src 64F */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}};
#else
const char impl[CV_DEPTH_MAX][CV_DEPTH_MAX][4] = {
/* src 8U */ {{1,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 8S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 16U */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 16S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 32S */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}},
/* src 32F */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,0,0,0},{0,0,0,0}},
/* src 64F */ {{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}}};
#endif // IPP_CALLS_ENFORCED
if(impl[src_depth][dst_depth][cn-1] == 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if(fabs(delta) > FLT_EPSILON || fabs(scale-1) > FLT_EPSILON)
useScale = true;
// cv::Sobel accepts ksize == FILTER_SCHARR (-1, i.e. ksize <= 0) which selects the 3x3
// Scharr derivative, so the Sobel entry point may legitimately request a Scharr filter.
if(ksize <= 0)
{
ksize = 3;
useScharr = true;
}
IppiMaskSize maskSize = ippiGetMaskSize(ksize, ksize);
if((int)maskSize < 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
#if IPP_VERSION_X100 <= 201703
// Bug with mirror wrap
if(borderType == cv::BORDER_REFLECT_101 && (ksize/2+1 > width || ksize/2+1 > height))
return CV_HAL_ERROR_NOT_IMPLEMENTED;
#endif
IwiDerivativeType derivType = ippiGetDerivType(dx, dy, (useScharr)?false:true);
if((int)derivType < 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
try
{
::ipp::IwiImage iwSrc = ippiGetImage(src_depth, cn, src_data, src_step, width, height,
margin_left, margin_top, margin_right, margin_bottom);
::ipp::IwiImage iwDst = ippiGetImage(dst_depth, cn, dst_data, dst_step, width, height,
0, 0, 0, 0);
::ipp::IwiImage iwSrcProc = iwSrc;
::ipp::IwiImage iwDstProc = iwDst;
::ipp::IwiBorderSize borderSize(maskSize);
::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
if(!ippBorder)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
// IPP needs an extra iwiScale pass for 32f output with scale/delta, slower than OpenCV's fused approach
if(useScale && dstType == ipp32f)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if(srcType == ipp8u && dstType == ipp8u)
{
iwDstProc.Alloc(iwDst.m_size, ipp16s, cn);
useScale = true;
}
if(useScharr)
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterScharr, iwSrcProc, iwDstProc, derivType, maskSize, ::ipp::IwDefault(), ippBorder);
else
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterSobel, iwSrcProc, iwDstProc, derivType, maskSize, ::ipp::IwDefault(), ippBorder);
if(useScale)
CV_INSTRUMENT_FUN_IPP(::ipp::iwiScale, iwDstProc, iwDst, scale, delta, ::ipp::IwiScaleParams(ippAlgHintFast));
}
catch (const ::ipp::IwException &)
{
return CV_HAL_ERROR_NOT_IMPLEMENTED;
}
return CV_HAL_ERROR_OK;
}
int ipp_hal_sobel(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
int width, int height, int src_depth, int dst_depth, int cn,
int margin_left, int margin_top, int margin_right, int margin_bottom,
int dx, int dy, int ksize, double scale, double delta, int border_type)
{
return ipp_Deriv(src_data, src_step, dst_data, dst_step, width, height, src_depth, dst_depth, cn,
margin_left, margin_top, margin_right, margin_bottom,
dx, dy, ksize, scale, delta, border_type, false);
}
int ipp_hal_scharr(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step,
int width, int height, int src_depth, int dst_depth, int cn,
int margin_left, int margin_top, int margin_right, int margin_bottom,
int dx, int dy, double scale, double delta, int border_type)
{
return ipp_Deriv(src_data, src_step, dst_data, dst_step, width, height, src_depth, dst_depth, cn,
margin_left, margin_top, margin_right, margin_bottom,
dx, dy, 0, scale, delta, border_type, true);
}
#endif // HAVE_IPP_IW
#endif // IPP_VERSION_X100 >= 810