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:
committed by
GitHub
parent
7230c1ce08
commit
b022a9b321
@@ -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
|
||||
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
#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"
|
||||
|
||||
@@ -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 <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(),
|
||||
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<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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user