diff --git a/hal/ipp/CMakeLists.txt b/hal/ipp/CMakeLists.txt index f4cae58364..b162d5ebc4 100644 --- a/hal/ipp/CMakeLists.txt +++ b/hal/ipp/CMakeLists.txt @@ -23,6 +23,7 @@ add_library(ipphal STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/matchtemplate_ipp.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/canny_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 856ea5d222..8894d4e4c6 100644 --- a/hal/ipp/include/ipp_hal_imgproc.hpp +++ b/hal/ipp/include/ipp_hal_imgproc.hpp @@ -146,4 +146,20 @@ int ipp_hal_matchTemplate(const uchar* src_data, size_t src_step, int src_width, #endif // IPP_VERSION_X100 >= 700 +#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better + +#if defined(HAVE_IPP_IW) +int ipp_hal_canny(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int cn, + double lowThreshold, double highThreshold, int ksize, bool L2gradient); +#undef cv_hal_canny +#define cv_hal_canny ipp_hal_canny + +int ipp_hal_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step, + uchar* dst_data, size_t dst_step, int width, int height, int cn, + double lowThreshold, double highThreshold, bool L2gradient); +#undef cv_hal_canny_deriv +#define cv_hal_canny_deriv ipp_hal_canny_deriv +#endif + #endif //__IPP_HAL_IMGPROC_HPP__ diff --git a/hal/ipp/src/canny_ipp.cpp b/hal/ipp/src/canny_ipp.cpp new file mode 100644 index 0000000000..d11a580b73 --- /dev/null +++ b/hal/ipp/src/canny_ipp.cpp @@ -0,0 +1,95 @@ +// 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" + +#ifdef HAVE_IPP_IW + +#include +#include "precomp_ipp.hpp" + +int ipp_hal_canny(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, + int width, int height, int cn, + double lowThreshold, double highThreshold, int ksize, bool L2gradient) +{ + CV_HAL_CHECK_USE_IPP(); + +#if IPP_DISABLE_PERF_CANNY_MT + if(cv::getNumThreads() > 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; +#endif + + if(width <= 3 || height <= 3) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if(cn != 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + IppiMaskSize kernel; + if(ksize == 3) + kernel = ippMskSize3x3; + else if(ksize == 5) + kernel = ippMskSize5x5; + else + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + IppNormType norm = L2gradient ? ippNormL2 : ippNormL1; + + try + { + ::ipp::IwiImage iwSrc, iwDst; + iwSrc.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), (void*)src_data, IwSize(src_step)); + iwDst.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), dst_data, IwSize(dst_step)); + + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCanny, iwSrc, iwDst, (float)lowThreshold, (float)highThreshold, + ::ipp::IwiFilterCannyParams(ippFilterSobel, kernel, norm), ippBorderRepl); + } + catch (const ::ipp::IwException &) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + return CV_HAL_ERROR_OK; +} + +int ipp_hal_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step, + uchar* dst_data, size_t dst_step, int width, int height, int cn, + double lowThreshold, double highThreshold, bool L2gradient) +{ + CV_HAL_CHECK_USE_IPP(); + +#if IPP_DISABLE_PERF_CANNY_MT + if(cv::getNumThreads() > 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; +#endif + + if(width <= 3 || height <= 3) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + if(cn != 1) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + IppNormType norm = L2gradient ? ippNormL2 : ippNormL1; + + try + { + ::ipp::IwiImage iwSrcDx, iwSrcDy, iwDst; + iwSrcDx.Init(IwiSize{width, height}, ipp16s, cn, ::ipp::IwiBorderSize(), (void*)dx_data, IwSize(dx_step)); + iwSrcDy.Init(IwiSize{width, height}, ipp16s, cn, ::ipp::IwiBorderSize(), (void*)dy_data, IwSize(dy_step)); + iwDst.Init(IwiSize{width, height}, ipp8u, cn, ::ipp::IwiBorderSize(), dst_data, IwSize(dst_step)); + + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCannyDeriv, iwSrcDx, iwSrcDy, iwDst, (float)lowThreshold, (float)highThreshold, + ::ipp::IwiFilterCannyDerivParams(norm)); + } + catch (const ::ipp::IwException &) + { + return CV_HAL_ERROR_NOT_IMPLEMENTED; + } + + return CV_HAL_ERROR_OK; +} + +#endif diff --git a/modules/core/include/opencv2/core/private.hpp b/modules/core/include/opencv2/core/private.hpp index d6f4425be2..769fb9f605 100644 --- a/modules/core/include/opencv2/core/private.hpp +++ b/modules/core/include/opencv2/core/private.hpp @@ -211,7 +211,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); } // Temporary disabled named IPP region. Performance #define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations #define IPP_DISABLE_PERF_TRUE_DIST_MT 1 // cv::distanceTransform OpenCV MT performance is better -#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better #ifdef HAVE_IPP #include "ippversion.h" diff --git a/modules/imgproc/src/canny.cpp b/modules/imgproc/src/canny.cpp index 29696139a1..ed391cbd99 100644 --- a/modules/imgproc/src/canny.cpp +++ b/modules/imgproc/src/canny.cpp @@ -48,85 +48,6 @@ namespace cv { -#ifdef HAVE_IPP -static bool ipp_Canny(const Mat& src , const Mat& dx_, const Mat& dy_, Mat& dst, float low, float high, bool L2gradient, int aperture_size) -{ -#ifdef HAVE_IPP_IW - CV_INSTRUMENT_REGION_IPP(); - -#if IPP_DISABLE_PERF_CANNY_MT - if(cv::getNumThreads()>1) - return false; -#endif - - ::ipp::IwiSize size(dst.cols, dst.rows); - IppDataType type = ippiGetDataType(dst.depth()); - int channels = dst.channels(); - IppNormType norm = (L2gradient)?ippNormL2:ippNormL1; - - if(size.width <= 3 || size.height <= 3) - return false; - - if(channels != 1) - return false; - - if(type != ipp8u) - return false; - - if(src.empty()) - { - try - { - ::ipp::IwiImage iwSrcDx; - ::ipp::IwiImage iwSrcDy; - ::ipp::IwiImage iwDst; - - ippiGetImage(dx_, iwSrcDx); - ippiGetImage(dy_, iwSrcDy); - ippiGetImage(dst, iwDst); - - CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCannyDeriv, iwSrcDx, iwSrcDy, iwDst, low, high, ::ipp::IwiFilterCannyDerivParams(norm)); - } - catch (const ::ipp::IwException &) - { - return false; - } - } - else - { - IppiMaskSize kernel; - - if(aperture_size == 3) - kernel = ippMskSize3x3; - else if(aperture_size == 5) - kernel = ippMskSize5x5; - else - return false; - - try - { - ::ipp::IwiImage iwSrc; - ::ipp::IwiImage iwDst; - - ippiGetImage(src, iwSrc); - ippiGetImage(dst, iwDst); - - CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterCanny, iwSrc, iwDst, low, high, ::ipp::IwiFilterCannyParams(ippFilterSobel, kernel, norm), ippBorderRepl); - } - catch (const ::ipp::IwException &) - { - return false; - } - } - - return true; -#else - CV_UNUSED(src); CV_UNUSED(dx_); CV_UNUSED(dy_); CV_UNUSED(dst); CV_UNUSED(low); CV_UNUSED(high); CV_UNUSED(L2gradient); CV_UNUSED(aperture_size); - return false; -#endif -} -#endif - #ifdef HAVE_OPENCL template @@ -803,8 +724,6 @@ void Canny( InputArray _src, OutputArray _dst, CALL_HAL(canny, cv_hal_canny, src.data, src.step, dst.data, dst.step, src.cols, src.rows, src.channels(), low_thresh, high_thresh, aperture_size, L2gradient); - CV_IPP_RUN_FAST(ipp_Canny(src, Mat(), Mat(), dst, (float)low_thresh, (float)high_thresh, L2gradient, aperture_size)) - if (L2gradient) { low_thresh = std::min(32767.0, low_thresh); @@ -879,7 +798,8 @@ void Canny( InputArray _dx, InputArray _dy, OutputArray _dst, Mat dx = _dx.getMat(); Mat dy = _dy.getMat(); - CV_IPP_RUN_FAST(ipp_Canny(Mat(), dx, dy, dst, (float)low_thresh, (float)high_thresh, L2gradient, 0)) + CALL_HAL(canny_deriv, cv_hal_canny_deriv, dx.ptr(), dx.step, dy.ptr(), dy.step, + dst.data, dst.step, dx.cols, dx.rows, dx.channels(), low_thresh, high_thresh, L2gradient); if (L2gradient) { diff --git a/modules/imgproc/src/hal_replacement.hpp b/modules/imgproc/src/hal_replacement.hpp index f642a3709b..6a869e0a9a 100644 --- a/modules/imgproc/src/hal_replacement.hpp +++ b/modules/imgproc/src/hal_replacement.hpp @@ -1520,6 +1520,27 @@ inline int hal_ni_canny(const uchar* src_data, size_t src_step, uchar* dst_data, #define cv_hal_canny hal_ni_canny //! @endcond +/** + @brief Canny edge detector from image derivatives + @param dx_data Source image x-derivative data + @param dx_step Source image x-derivative step + @param dy_data Source image y-derivative data + @param dy_step Source image y-derivative step + @param dst_data Destination image data + @param dst_step Destination image step + @param width Source image width + @param height Source image height + @param cn Number of channels + @param lowThreshold low hresholds value + @param highThreshold high thresholds value + @param L2gradient Flag, indicating use L2 or L1 norma. +*/ +inline int hal_ni_canny_deriv(const short* dx_data, size_t dx_step, const short* dy_data, size_t dy_step, uchar* dst_data, size_t dst_step, int width, int height, int cn, double lowThreshold, double highThreshold, bool L2gradient) { return CV_HAL_ERROR_NOT_IMPLEMENTED; } + +//! @cond IGNORED +#define cv_hal_canny_deriv hal_ni_canny_deriv +//! @endcond + /** @brief Calculates all of the moments up to the third order of a polygon or rasterized shape for image @param src_data Source image data