mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #29420 from Prasadayus:box_filter_ipp_extract
Extract IPP integration as HAL function for box_filter #29420 Backport of https://github.com/opencv/opencv/pull/29414 **Performance Numbers on Intel(R) Core(TM) i9-11900K:** https://docs.google.com/spreadsheets/d/1kMKiZWh--pH30hqsQo6j1suNw1lfQiKzSankMCMa2FI/edit?usp=sharing ### 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:
committed by
GitHub
parent
e6d0c0340b
commit
c77286749a
@@ -18,6 +18,7 @@ add_library(ipphal STATIC
|
||||
"${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/box_filter_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/sum_ipp.cpp"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp"
|
||||
)
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
#include <opencv2/core/base.hpp>
|
||||
#include "ipp_utils.hpp"
|
||||
|
||||
#if IPP_VERSION_X100 >= 810
|
||||
// Disabled in https://github.com/opencv/opencv/pull/13085 due large binary size
|
||||
#define DISABLE_IPP_BOX_FILTER 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,
|
||||
int dst_height, const double M[6], int interpolation, int borderType, const double borderValue[4]);
|
||||
@@ -49,6 +51,16 @@ int ipp_hal_resize(int src_type, const uchar *src_data, size_t src_step, int src
|
||||
#define cv_hal_resize ipp_hal_resize
|
||||
#endif // HAVE_IPP_IW
|
||||
|
||||
#if defined(HAVE_IPP_IW) && !DISABLE_IPP_BOX_FILTER
|
||||
int ipp_hal_boxFilter(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,
|
||||
size_t ksize_width, size_t ksize_height, int anchor_x, int anchor_y,
|
||||
bool normalize, int border_type);
|
||||
#undef cv_hal_boxFilter
|
||||
#define cv_hal_boxFilter ipp_hal_boxFilter
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_BOX_FILTER
|
||||
|
||||
int ipp_hal_remap32f(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, int dst_height,
|
||||
float* mapx, size_t mapx_step, float* mapy, size_t mapy_step,
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
// 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"
|
||||
|
||||
#if defined(HAVE_IPP_IW) && !DISABLE_IPP_BOX_FILTER
|
||||
|
||||
namespace cv { namespace ipp { unsigned long long getIppTopFeatures(); } }
|
||||
|
||||
// Copied from core/private.hpp (gated by HAVE_IPP, which the plugin lacks).
|
||||
// boxGetIppBorderType: distinct name, adds the REFLECT_101 precomp's version drops.
|
||||
static inline IppiBorderType boxGetIppBorderType(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 = boxGetIppBorderType(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_boxFilter(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,
|
||||
size_t ksize_width, size_t ksize_height,
|
||||
int anchor_x, int anchor_y,
|
||||
bool normalize, int border_type)
|
||||
{
|
||||
CV_HAL_CHECK_USE_IPP();
|
||||
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// Problem with SSE42 optimization for 16s and some 8u modes
|
||||
if(cv::ipp::getIppTopFeatures() == ippCPUID_SSE42 &&
|
||||
(((src_depth == CV_16S || src_depth == CV_16U) && (cn == 3 || cn == 4)) ||
|
||||
(src_depth == CV_8U && cn == 3 && (ksize_width > 5 || ksize_height > 5))))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
// Other optimizations has some degradations too
|
||||
if(((src_depth == CV_16S || src_depth == CV_16U) && cn == 4) ||
|
||||
(src_depth == CV_8U && cn == 1 && (ksize_width > 5 || ksize_height > 5)))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
#endif
|
||||
|
||||
if(!normalize)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
if(!ippiCheckAnchor(anchor_x, anchor_y, (int)ksize_width, (int)ksize_height))
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
try
|
||||
{
|
||||
// raw-pointer equivalent of ippiGetImage: margins are the in-memory border
|
||||
::ipp::IwiBorderSize inMemBorder;
|
||||
inMemBorder.left = (IwSize)margin_left;
|
||||
inMemBorder.top = (IwSize)margin_top;
|
||||
inMemBorder.right = (IwSize)margin_right;
|
||||
inMemBorder.bottom = (IwSize)margin_bottom;
|
||||
|
||||
::ipp::IwiImage iwSrc, iwDst;
|
||||
iwSrc.Init(IwiSize{width, height}, ippiGetDataType(src_depth), cn,
|
||||
inMemBorder, (void*)src_data, IwSize(src_step));
|
||||
iwDst.Init(IwiSize{width, height}, ippiGetDataType(dst_depth), cn,
|
||||
::ipp::IwiBorderSize(), dst_data, IwSize(dst_step));
|
||||
|
||||
::ipp::IwiSize iwKSize{(int)ksize_width, (int)ksize_height};
|
||||
::ipp::IwiBorderSize borderSize(iwKSize);
|
||||
::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, border_type, borderSize));
|
||||
if(!ippBorder)
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBox, iwSrc, iwDst, iwKSize, ::ipp::IwDefault(), ippBorder);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return CV_HAL_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CV_HAL_ERROR_OK;
|
||||
}
|
||||
|
||||
#endif // defined(HAVE_IPP_IW) && !DISABLE_IPP_BOX_FILTER
|
||||
@@ -314,52 +314,6 @@ Ptr<FilterEngine> createBoxFilter(int srcType, int dstType, Size ksize,
|
||||
CV_CPU_DISPATCH_MODES_ALL);
|
||||
}
|
||||
|
||||
#if 0 //defined(HAVE_IPP)
|
||||
static bool ipp_boxfilter(Mat &src, Mat &dst, Size ksize, Point anchor, bool normalize, int borderType)
|
||||
{
|
||||
#ifdef HAVE_IPP_IW
|
||||
CV_INSTRUMENT_REGION_IPP();
|
||||
|
||||
#if IPP_VERSION_X100 < 201801
|
||||
// Problem with SSE42 optimization for 16s and some 8u modes
|
||||
if(ipp::getIppTopFeatures() == ippCPUID_SSE42 && (((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 3 || src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 3 && (ksize.width > 5 || ksize.height > 5))))
|
||||
return false;
|
||||
|
||||
// Other optimizations has some degradations too
|
||||
if((((src.depth() == CV_16S || src.depth() == CV_16U) && (src.channels() == 4)) || (src.depth() == CV_8U && src.channels() == 1 && (ksize.width > 5 || ksize.height > 5))))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if(!normalize)
|
||||
return false;
|
||||
|
||||
if(!ippiCheckAnchor(anchor, ksize))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
::ipp::IwiImage iwSrc = ippiGetImage(src);
|
||||
::ipp::IwiImage iwDst = ippiGetImage(dst);
|
||||
::ipp::IwiSize iwKSize = ippiGetSize(ksize);
|
||||
::ipp::IwiBorderSize borderSize(iwKSize);
|
||||
::ipp::IwiBorderType ippBorder(ippiGetBorder(iwSrc, borderType, borderSize));
|
||||
if(!ippBorder)
|
||||
return false;
|
||||
|
||||
CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBox, iwSrc, iwDst, iwKSize, ::ipp::IwDefault(), ippBorder);
|
||||
}
|
||||
catch (const ::ipp::IwException &)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
CV_UNUSED(src); CV_UNUSED(dst); CV_UNUSED(ksize); CV_UNUSED(anchor); CV_UNUSED(normalize); CV_UNUSED(borderType);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void boxFilter(InputArray _src, OutputArray _dst, int ddepth,
|
||||
@@ -401,7 +355,6 @@ void boxFilter(InputArray _src, OutputArray _dst, int ddepth,
|
||||
ofs.x, ofs.y, wsz.width - src.cols - ofs.x, wsz.height - src.rows - ofs.y, ksize.width, ksize.height,
|
||||
anchor.x, anchor.y, normalize, borderType&~BORDER_ISOLATED);
|
||||
|
||||
//CV_IPP_RUN_FAST(ipp_boxfilter(src, dst, ksize, anchor, normalize, borderType));
|
||||
|
||||
borderType = (borderType&~BORDER_ISOLATED);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user