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

Merge pull request #29434 from Prasadayus:canny_ipp_extract

Extracting IPP integaration as HAL for Canny #29434

Backport of : https://github.com/opencv/opencv/pull/29433

**Performance Numbers on Intel(R) Core(TM) i9-11900K:** https://docs.google.com/spreadsheets/d/1RMvUZP1tSQtdjuNQY9JasYmlx1L5iN9XWGhXtG5u1uI/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:
Prasad Ayush Kumar
2026-07-10 11:59:24 +01:00
committed by GitHub
parent 7230c1ce08
commit b022a9b321
6 changed files with 135 additions and 83 deletions
+1
View File
@@ -23,6 +23,7 @@ add_library(ipphal STATIC
"${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/color_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/filter_ipp.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/matchtemplate_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 #TODO: HAVE_IPP_ICV and HAVE_IPP_IW added as private macro till OpenCV itself is
+16
View File
@@ -146,4 +146,20 @@ int ipp_hal_matchTemplate(const uchar* src_data, size_t src_step, int src_width,
#endif // IPP_VERSION_X100 >= 700 #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__ #endif //__IPP_HAL_IMGPROC_HPP__
+95
View File
@@ -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 <opencv2/core.hpp>
#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
@@ -211,7 +211,6 @@ T* allocSingletonNew() { return new(allocSingletonNewBuffer(sizeof(T))) T(); }
// Temporary disabled named IPP region. Performance // Temporary disabled named IPP region. Performance
#define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations #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_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 #ifdef HAVE_IPP
#include "ippversion.h" #include "ippversion.h"
+2 -82
View File
@@ -48,85 +48,6 @@
namespace cv 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 #ifdef HAVE_OPENCL
template <bool useCustomDeriv> template <bool useCustomDeriv>
@@ -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(), 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); 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) if (L2gradient)
{ {
low_thresh = std::min(32767.0, low_thresh); 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 dx = _dx.getMat();
Mat dy = _dy.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<short>(), dx.step, dy.ptr<short>(), dy.step,
dst.data, dst.step, dx.cols, dx.rows, dx.channels(), low_thresh, high_thresh, L2gradient);
if (L2gradient) if (L2gradient)
{ {
+21
View File
@@ -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 #define cv_hal_canny hal_ni_canny
//! @endcond //! @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 @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 @param src_data Source image data