From d19dd94deefcc7ef700a6a872231cab3efc5dfc0 Mon Sep 17 00:00:00 2001 From: ekharkov Date: Tue, 8 Jul 2025 12:31:40 +0200 Subject: [PATCH] Moved IPP remap to HAL --- hal/ipp/include/ipp_hal_imgproc.hpp | 9 ++ hal/ipp/src/precomp_ipp.hpp | 12 +++ hal/ipp/src/warp_ipp.cpp | 127 ++++++++++++++++++++++- modules/imgproc/src/imgwarp.cpp | 151 ---------------------------- 4 files changed, 143 insertions(+), 156 deletions(-) diff --git a/hal/ipp/include/ipp_hal_imgproc.hpp b/hal/ipp/include/ipp_hal_imgproc.hpp index bafbf3faaf..29ebee241d 100644 --- a/hal/ipp/include/ipp_hal_imgproc.hpp +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -24,4 +24,13 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step #define cv_hal_warpPerspective ipp_hal_warpPerspective #endif + +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, + int interpolation, int border_type, const double border_value[4]); +#undef cv_hal_remap32f +#define cv_hal_remap32f ipp_hal_remap32f + + #endif //__IPP_HAL_IMGPROC_HPP__ diff --git a/hal/ipp/src/precomp_ipp.hpp b/hal/ipp/src/precomp_ipp.hpp index b63e660a94..bff2d499b1 100644 --- a/hal/ipp/src/precomp_ipp.hpp +++ b/hal/ipp/src/precomp_ipp.hpp @@ -11,6 +11,18 @@ #include "iw++/iw.hpp" #endif +static inline IppiSize ippiSize(size_t width, size_t height) +{ + IppiSize size = { (int)width, (int)height }; + return size; +} + +static inline IppiSize ippiSize(const cv::Size & _size) +{ + IppiSize size = { _size.width, _size.height }; + return size; +} + static inline IppDataType ippiGetDataType(int depth) { depth = CV_MAT_DEPTH(depth); diff --git a/hal/ipp/src/warp_ipp.cpp b/hal/ipp/src/warp_ipp.cpp index a41d51460a..ffad2e13e2 100644 --- a/hal/ipp/src/warp_ipp.cpp +++ b/hal/ipp/src/warp_ipp.cpp @@ -133,21 +133,22 @@ int ipp_hal_warpAffine(int src_type, const uchar *src_data, size_t src_step, int return CV_HAL_ERROR_OK; } #endif +#endif typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); template -bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) +bool IPPSetSimple(const double value[4], void *dataPointer, int step, IppiSize &size, ippiSetFunc func) { //CV_INSTRUMENT_REGION_IPP(); Type values[channels]; for( int i = 0; i < channels; i++ ) values[i] = cv::saturate_cast(value[i]); - return func(values, dataPointer, step, size) >= 0; + return CV_INSTRUMENT_FUN_IPP(func, values, dataPointer, step, size) >= 0; } -static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) +static bool IPPSet(const double value[4], void *dataPointer, int step, IppiSize &size, int channels, int depth) { //CV_INSTRUMENT_REGION_IPP(); @@ -248,7 +249,7 @@ public: { IppiSize setSize = {dst.cols, range.end - range.start}; void *dataPointer = dst.ptr(range.start); - if( !IPPSet( cv::Scalar(borderValue[0], borderValue[1], borderValue[2], borderValue[3]), dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) + if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) ) { *ok = false; return; @@ -364,4 +365,120 @@ int ipp_hal_warpPerspective(int src_type, const uchar *src_data, size_t src_step return CV_HAL_ERROR_OK; } #endif -#endif + +typedef IppStatus(CV_STDCALL *ippiRemap)(const void *pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, + const Ipp32f *pxMap, int xMapStep, const Ipp32f *pyMap, int yMapStep, + void *pDst, int dstStep, IppiSize dstRoiSize, int interpolation); + +class IPPRemapInvoker : public cv::ParallelLoopBody +{ +public: + IPPRemapInvoker(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, float *_mapx, size_t _mapx_step, float *_mapy, + size_t _mapy_step, ippiRemap _ippFunc, int _ippInterpolation, int _borderType, const double _borderValue[4], bool *_ok) : + ParallelLoopBody(), + src_type(_src_type), src(_src_data), src_step(_src_step), src_width(_src_width), src_height(_src_height), + dst(_dst_data), dst_step(_dst_step), dst_width(_dst_width), mapx(_mapx), mapx_step(_mapx_step), mapy(_mapy), + mapy_step(_mapy_step), ippFunc(_ippFunc), ippInterpolation(_ippInterpolation), borderType(_borderType), ok(_ok) + { + memcpy(this->borderValue, _borderValue, sizeof(this->borderValue)); + *ok = true; + } + + virtual void operator()(const cv::Range &range) const + { + IppiRect srcRoiRect = {0, 0, src_width, src_height}; + uchar *dst_roi_data = dst + range.start * dst_step; + IppiSize dstRoiSize = ippiSize(dst_width, range.size()); + int depth = CV_MAT_DEPTH(src_type), cn = CV_MAT_CN(src_type); + + if (borderType == cv::BORDER_CONSTANT && + !IPPSet(borderValue, dst_roi_data, (int)dst_step, dstRoiSize, cn, depth)) + { + *ok = false; + return; + } + + if (CV_INSTRUMENT_FUN_IPP(ippFunc, src, {src_width, src_height}, (int)src_step, srcRoiRect, + mapx, (int)mapx_step, mapy, (int)mapy_step, + dst_roi_data, (int)dst_step, dstRoiSize, ippInterpolation) < 0) + *ok = false; + else + { + CV_IMPL_ADD(CV_IMPL_IPP | CV_IMPL_MT); + } + } + +private: + int src_type; + const uchar *src; + size_t src_step; + int src_width, src_height; + uchar *dst; + size_t dst_step; + int dst_width; + float *mapx; + size_t mapx_step; + float *mapy; + size_t mapy_step; + ippiRemap ippFunc; + int ippInterpolation, borderType; + double borderValue[4]; + bool *ok; +}; + +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, + int interpolation, int border_type, const double border_value[4]) +{ + if ((interpolation == cv::INTER_LINEAR || interpolation == cv::INTER_CUBIC || interpolation == cv::INTER_NEAREST) && + (border_type == cv::BORDER_CONSTANT || border_type == cv::BORDER_TRANSPARENT)) + { + int ippInterpolation = + interpolation == cv::INTER_NEAREST ? IPPI_INTER_NN : interpolation == cv::INTER_LINEAR ? IPPI_INTER_LINEAR + : IPPI_INTER_CUBIC; + + /* C1 C2 C3 C4 */ + char impl[CV_DEPTH_MAX][4][3]={{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8U + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //8S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //16U + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //16S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32S + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}, //32F + {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}; //64F + + if (impl[CV_TYPE(src_type)][CV_MAT_CN(src_type) - 1][interpolation] == 0) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + ippiRemap ippFunc = + src_type == CV_8UC1 ? (ippiRemap)ippiRemap_8u_C1R : src_type == CV_8UC3 ? (ippiRemap)ippiRemap_8u_C3R + : src_type == CV_8UC4 ? (ippiRemap)ippiRemap_8u_C4R + : src_type == CV_16UC1 ? (ippiRemap)ippiRemap_16u_C1R + : src_type == CV_16UC3 ? (ippiRemap)ippiRemap_16u_C3R + : src_type == CV_16UC4 ? (ippiRemap)ippiRemap_16u_C4R + : src_type == CV_32FC1 ? (ippiRemap)ippiRemap_32f_C1R + : src_type == CV_32FC3 ? (ippiRemap)ippiRemap_32f_C3R + : src_type == CV_32FC4 ? (ippiRemap)ippiRemap_32f_C4R + : 0; + + if (ippFunc) + { + bool ok; + + IPPRemapInvoker invoker(src_type, src_data, src_step, src_width, src_height, dst_data, dst_step, dst_width, + mapx, mapx_step, mapy, mapy_step, ippFunc, ippInterpolation, border_type, border_value, &ok); + cv::Range range(0, dst_height); + cv::parallel_for_(range, invoker, dst_width * dst_height / (double)(1 << 16)); + + if (ok) + { + CV_IMPL_ADD(CV_IMPL_IPP | CV_IMPL_MT); + return CV_HAL_ERROR_OK; + } + } + } + return CV_HAL_ERROR_NOT_IMPLEMENTED; +} diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index 4690265420..602ed802a2 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -60,66 +60,6 @@ using namespace cv; namespace cv { -#if defined (HAVE_IPP) && (!IPP_DISABLE_REMAP) -typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize); - -template -bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func) -{ - CV_INSTRUMENT_REGION_IPP(); - - Type values[channels]; - for( int i = 0; i < channels; i++ ) - values[i] = saturate_cast(value[i]); - return func(values, dataPointer, step, size) >= 0; -} - -static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth) -{ - CV_INSTRUMENT_REGION_IPP(); - - if( channels == 1 ) - { - switch( depth ) - { - case CV_8U: - return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R, saturate_cast(value[0]), (Ipp8u *)dataPointer, step, size) >= 0; - case CV_16U: - return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R, saturate_cast(value[0]), (Ipp16u *)dataPointer, step, size) >= 0; - case CV_32F: - return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R, saturate_cast(value[0]), (Ipp32f *)dataPointer, step, size) >= 0; - } - } - else - { - if( channels == 3 ) - { - switch( depth ) - { - case CV_8U: - return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R); - case CV_16U: - return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R); - case CV_32F: - return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R); - } - } - else if( channels == 4 ) - { - switch( depth ) - { - case CV_8U: - return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R); - case CV_16U: - return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R); - case CV_32F: - return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R); - } - } - } - return false; -} -#endif /************** interpolation formulas and tables ***************/ @@ -1572,57 +1512,7 @@ static bool ocl_logPolar(InputArray _src, OutputArray _dst, #endif -#if defined HAVE_IPP && !IPP_DISABLE_REMAP -typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi, - const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep, - void * pDst, int dstStep, IppiSize dstRoiSize, int interpolation); - -class IPPRemapInvoker : - public ParallelLoopBody -{ -public: - IPPRemapInvoker(Mat & _src, Mat & _dst, Mat & _xmap, Mat & _ymap, ippiRemap _ippFunc, - int _ippInterpolation, int _borderType, const Scalar & _borderValue, bool * _ok) : - ParallelLoopBody(), src(_src), dst(_dst), map1(_xmap), map2(_ymap), ippFunc(_ippFunc), - ippInterpolation(_ippInterpolation), borderType(_borderType), borderValue(_borderValue), ok(_ok) - { - *ok = true; - } - - virtual void operator() (const Range & range) const - { - IppiRect srcRoiRect = { 0, 0, src.cols, src.rows }; - Mat dstRoi = dst.rowRange(range); - IppiSize dstRoiSize = ippiSize(dstRoi.size()); - int type = dst.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type); - - if (borderType == BORDER_CONSTANT && - !IPPSet(borderValue, dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, cn, depth)) - { - *ok = false; - return; - } - - if (CV_INSTRUMENT_FUN_IPP(ippFunc, src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect, - map1.ptr(), (int)map1.step, map2.ptr(), (int)map2.step, - dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation) < 0) - *ok = false; - else - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - } - } - -private: - Mat & src, & dst, & map1, & map2; - ippiRemap ippFunc; - int ippInterpolation, borderType; - Scalar borderValue; - bool * ok; -}; - -#endif } @@ -1737,47 +1627,6 @@ void cv::remap( InputArray _src, OutputArray _dst, int type = src.type(), depth = CV_MAT_DEPTH(type); -#if defined HAVE_IPP && !IPP_DISABLE_REMAP - CV_IPP_CHECK() - { - if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) && - map1.type() == CV_32FC1 && map2.type() == CV_32FC1 && - (borderType == BORDER_CONSTANT || borderType == BORDER_TRANSPARENT)) - { - int ippInterpolation = - interpolation == INTER_NEAREST ? IPPI_INTER_NN : - interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : IPPI_INTER_CUBIC; - - ippiRemap ippFunc = - type == CV_8UC1 ? (ippiRemap)ippiRemap_8u_C1R : - type == CV_8UC3 ? (ippiRemap)ippiRemap_8u_C3R : - type == CV_8UC4 ? (ippiRemap)ippiRemap_8u_C4R : - type == CV_16UC1 ? (ippiRemap)ippiRemap_16u_C1R : - type == CV_16UC3 ? (ippiRemap)ippiRemap_16u_C3R : - type == CV_16UC4 ? (ippiRemap)ippiRemap_16u_C4R : - type == CV_32FC1 ? (ippiRemap)ippiRemap_32f_C1R : - type == CV_32FC3 ? (ippiRemap)ippiRemap_32f_C3R : - type == CV_32FC4 ? (ippiRemap)ippiRemap_32f_C4R : 0; - - if (ippFunc) - { - bool ok; - IPPRemapInvoker invoker(src, dst, map1, map2, ippFunc, ippInterpolation, - borderType, borderValue, &ok); - Range range(0, dst.rows); - parallel_for_(range, invoker, dst.total() / (double)(1 << 16)); - - if (ok) - { - CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT); - return; - } - setIppErrorStatus(); - } - } - } -#endif - RemapNNFunc nnfunc = 0; RemapFunc ifunc = 0; const void* ctab = 0;