From 062a00bab33667c861d002fb09b30780ca37e73a Mon Sep 17 00:00:00 2001 From: Akansha Mallick Date: Tue, 7 Jul 2026 15:21:34 +0530 Subject: [PATCH] Extracted IPP to HAL for threshold function --- hal/ipp/CMakeLists.txt | 1 + hal/ipp/include/ipp_hal_imgproc.hpp | 5 + hal/ipp/src/threshold_ipp.cpp | 128 ++++++++++++++++++++++++++ modules/imgproc/src/thresh.cpp | 136 ---------------------------- 4 files changed, 134 insertions(+), 136 deletions(-) create mode 100644 hal/ipp/src/threshold_ipp.cpp diff --git a/hal/ipp/CMakeLists.txt b/hal/ipp/CMakeLists.txt index b162d5ebc4..06022e2a84 100644 --- a/hal/ipp/CMakeLists.txt +++ b/hal/ipp/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(ipphal STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/matchtemplate_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/canny_ipp.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/threshold_ipp.cpp" ) #TODO: HAVE_IPP_ICV and HAVE_IPP_IW added as private macro till OpenCV itself is diff --git a/hal/ipp/include/ipp_hal_imgproc.hpp b/hal/ipp/include/ipp_hal_imgproc.hpp index 8894d4e4c6..28a447035e 100644 --- a/hal/ipp/include/ipp_hal_imgproc.hpp +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -144,6 +144,11 @@ int ipp_hal_matchTemplate(const uchar* src_data, size_t src_step, int src_width, #undef cv_hal_matchTemplate #define cv_hal_matchTemplate ipp_hal_matchTemplate +int ipp_hal_threshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int depth, int cn, double thresh, double maxValue, int thresholdType); +#undef cv_hal_threshold +#define cv_hal_threshold ipp_hal_threshold + #endif // IPP_VERSION_X100 >= 700 #define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better diff --git a/hal/ipp/src/threshold_ipp.cpp b/hal/ipp/src/threshold_ipp.cpp new file mode 100644 index 0000000000..352b240894 --- /dev/null +++ b/hal/ipp/src/threshold_ipp.cpp @@ -0,0 +1,128 @@ +// 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 +#include "precomp_ipp.hpp" + +#include +#include + +#if IPP_VERSION_X100 >= 700 + +int ipp_hal_threshold(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int depth, int cn, double thresh, double maxValue, + int thresholdType) +{ + CV_HAL_CHECK_USE_IPP(); + CV_UNUSED(maxValue); + + // IPP only implements these three types and depths; everything else falls back to OpenCV. + if (thresholdType != cv::THRESH_TRUNC && thresholdType != cv::THRESH_TOZERO && + thresholdType != cv::THRESH_TOZERO_INV) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + if (depth != CV_8U && depth != CV_16S && depth != CV_32F) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + int roi_width = width * cn; // threshold is elementwise, so channels fold into the width + int roi_height = height; + int elemSize1 = (depth == CV_8U) ? 1 : (depth == CV_16S) ? 2 : 4; + + if (src_step == (size_t)roi_width * elemSize1 && dst_step == (size_t)roi_width * elemSize1) + { + roi_width *= roi_height; + roi_height = 1; + src_step = dst_step = (size_t)roi_width * elemSize1; + } + + IppiSize sz = { roi_width, roi_height }; + const bool inplace = (src_data == dst_data); + IppStatus status = ippStsErr; + + CV_SUPPRESS_DEPRECATED_START + switch (depth) + { + case CV_8U: + { + Ipp8u t = (Ipp8u)thresh; + switch (thresholdType) + { + case cv::THRESH_TRUNC: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1IR, dst_data, (int)dst_step, sz, t); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t); + break; + case cv::THRESH_TOZERO: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1IR, dst_data, (int)dst_step, sz, t + 1, 0); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t + 1, 0); + break; + case cv::THRESH_TOZERO_INV: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1IR, dst_data, (int)dst_step, sz, t, 0); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1R, src_data, (int)src_step, dst_data, (int)dst_step, sz, t, 0); + break; + } + break; + } + case CV_16S: + { + const Ipp16s* src = (const Ipp16s*)src_data; + Ipp16s* dst = (Ipp16s*)dst_data; + Ipp16s t = (Ipp16s)thresh; + switch (thresholdType) + { + case cv::THRESH_TRUNC: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1IR, dst, (int)dst_step, sz, t); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t); + break; + case cv::THRESH_TOZERO: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1IR, dst, (int)dst_step, sz, t + 1, 0); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t + 1, 0); + break; + case cv::THRESH_TOZERO_INV: + if (inplace) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1IR, dst, (int)dst_step, sz, t, 0); + if (!inplace || status < 0) + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1R, src, (int)src_step, dst, (int)dst_step, sz, t, 0); + break; + } + break; + } + case CV_32F: + { + const Ipp32f* src = (const Ipp32f*)src_data; + Ipp32f* dst = (Ipp32f*)dst_data; + Ipp32f t = (Ipp32f)thresh; + switch (thresholdType) + { + case cv::THRESH_TRUNC: + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, t); + break; + case cv::THRESH_TOZERO: + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, nextafterf(t, std::numeric_limits::infinity()), 0); + break; + case cv::THRESH_TOZERO_INV: + status = CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step, dst, (int)dst_step, sz, t, 0); + break; + } + break; + } + } + CV_SUPPRESS_DEPRECATED_END + + return status >= 0 ? CV_HAL_ERROR_OK : CV_HAL_ERROR_NOT_IMPLEMENTED; +} + +#endif // IPP_VERSION_X100 >= 700 diff --git a/modules/imgproc/src/thresh.cpp b/modules/imgproc/src/thresh.cpp index 09266393e2..5366781234 100644 --- a/modules/imgproc/src/thresh.cpp +++ b/modules/imgproc/src/thresh.cpp @@ -193,57 +193,6 @@ thresh_8u( const Mat& _src, Mat& _dst, uchar thresh, uchar maxval, int type ) src_step = dst_step = roi.width; } -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - IppiSize sz = { roi.width, roi.height }; - CV_SUPPRESS_DEPRECATED_START - switch( type ) - { - case THRESH_TRUNC: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh+1, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh + 1, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO_INV: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1IR, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_8u_C1R, _src.ptr(), (int)src_step, _dst.ptr(), (int)dst_step, sz, thresh, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - } - CV_SUPPRESS_DEPRECATED_END - } -#endif - int j = 0; const uchar* src = _src.ptr(); uchar* dst = _dst.ptr(); @@ -577,57 +526,6 @@ thresh_16s( const Mat& _src, Mat& _dst, short thresh, short maxval, int type ) src_step = dst_step = roi.width; } -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - IppiSize sz = { roi.width, roi.height }; - CV_SUPPRESS_DEPRECATED_START - switch( type ) - { - case THRESH_TRUNC: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh + 1, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO_INV: - if (_src.data == _dst.data && CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1IR, dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - if (CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_16s_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0) >= 0) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - } - CV_SUPPRESS_DEPRECATED_END - } -#endif - #if (CV_SIMD || CV_SIMD_SCALABLE) int i, j; v_int16 thresh8 = vx_setall_s16( thresh ); @@ -799,40 +697,6 @@ thresh_32f( const Mat& _src, Mat& _dst, float thresh, float maxval, int type ) roi.height = 1; } -#if defined(HAVE_IPP) - CV_IPP_CHECK() - { - IppiSize sz = { roi.width, roi.height }; - switch( type ) - { - case THRESH_TRUNC: - if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GT_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO: - if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_LTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, nextafterf(thresh, std::numeric_limits::infinity()), 0)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - case THRESH_TOZERO_INV: - if (0 <= CV_INSTRUMENT_FUN_IPP(ippiThreshold_GTVal_32f_C1R, src, (int)src_step*sizeof(src[0]), dst, (int)dst_step*sizeof(dst[0]), sz, thresh, 0)) - { - CV_IMPL_ADD(CV_IMPL_IPP); - return; - } - setIppErrorStatus(); - break; - } - } -#endif - #if (CV_SIMD || CV_SIMD_SCALABLE) int i, j; v_float32 thresh4 = vx_setall_f32( thresh );