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

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2026-07-14 09:13:24 +03:00
19 changed files with 922 additions and 522 deletions
@@ -197,7 +197,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"
+63 -52
View File
@@ -6,11 +6,8 @@
#include "opencv2/core/mat.hpp"
#include "opencl_kernels_core.hpp"
#undef HAVE_IPP
#undef CV_IPP_RUN_FAST
#define CV_IPP_RUN_FAST(f, ...)
#undef CV_IPP_RUN
#define CV_IPP_RUN(c, f, ...)
#define IPP_DISABLE_REDUCE 1
#define IPP_DISABLE_SORT 0
/*************************************************************************************************\
Matrix Operations
@@ -498,7 +495,7 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
#define reduceMinR32f reduceR_<float, float, OpMin<float> >
#define reduceMinR64f reduceR_<double,double,OpMin<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
{
int sstep = (int)srcmat.step, stype = srcmat.type(),
@@ -587,7 +584,7 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
#define reduceSum2C32f32f reduceC_<float, float, OpAddSqr<float>, OpSqr<float> >
#define reduceSum2C64f64f reduceC_<double,double,OpAddSqr<double>,OpSqr<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
#define reduceSumC8u64f reduceSumC_8u16u16s32f_64f
#define reduceSumC16u64f reduceSumC_8u16u16s32f_64f
#define reduceSumC16s64f reduceSumC_8u16u16s32f_64f
@@ -597,14 +594,14 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
#define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> >
#define reduceSumC16s64f reduceC_<short, double,OpAdd<double> >
#define reduceSumC32f64f reduceC_<float, double,OpAdd<double> >
#endif
#define reduceSum2C8u64f reduceC_<uchar, double,OpAddSqr<int>, OpSqr<int> >
#define reduceSum2C16u64f reduceC_<ushort,double,OpAddSqr<double>,OpSqr<double> >
#define reduceSum2C16s64f reduceC_<short, double,OpAddSqr<double>,OpSqr<double> >
#define reduceSum2C32f64f reduceC_<float, double,OpAddSqr<double>,OpSqr<double> >
#endif
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
#define REDUCE_OP(favor, optype, type1, type2) \
static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
{ \
@@ -629,7 +626,7 @@ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstm
}
#endif
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
REDUCE_OP(8u, Max, uchar, uchar)
REDUCE_OP(16u, Max, ushort, ushort)
REDUCE_OP(16s, Max, short, short)
@@ -642,7 +639,7 @@ REDUCE_OP(32f, Max, float, float)
#endif
#define reduceMaxC64f reduceC_<double,double,OpMax<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
REDUCE_OP(8u, Min, uchar, uchar)
REDUCE_OP(16u, Min, ushort, ushort)
REDUCE_OP(16s, Min, short, short)
@@ -1037,7 +1034,7 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
}
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
typedef IppStatus (CV_STDCALL *IppSortFunc)(void *pSrcDst, int len, Ipp8u *pBuffer);
static IppSortFunc getSortFunc(int depth, bool sortDescending)
@@ -1074,54 +1071,64 @@ static bool ipp_sort(const Mat& src, Mat& dst, int flags)
if(!ippsSortRadix_I)
return false;
if(sortRows)
{
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixGetBufferSize(src.cols, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
if(!inplace)
src.copyTo(dst);
for(int i = 0; i < dst.rows; i++)
{
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer.data()) < 0)
return false;
}
}
int n, len;
if( sortRows )
n = src.rows, len = src.cols;
else
n = src.cols, len = src.rows;
int bufferSize;
if(ippsSortRadixGetBufferSize(len, type, &bufferSize) < 0)
return false;
// Each row/column sorts independently, so parallelize over n like sort_ does.
// IPP scratch (buffer) and per-column temporaries are thread-local; a shared flag
// records IPP failures since the lambda cannot return from ipp_sort.
volatile bool ok = true;
parallel_for_(Range(0, n), [&](const Range& range)
{
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixGetBufferSize(src.rows, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
Mat row(1, src.rows, src.type());
Mat srcSub;
Mat dstSub;
AutoBuffer<Ipp8u> buffer(bufferSize);
Mat row;
Rect subRect(0,0,1,src.rows);
if( !sortRows )
row.create(1, src.rows, src.type());
for(int i = 0; i < src.cols; i++)
for( int i = range.start; i < range.end; i++ )
{
subRect.x = i;
srcSub = Mat(src, subRect);
dstSub = Mat(dst, subRect);
srcSub.copyTo(row);
if( !ok )
break;
void* ptr;
if( sortRows )
{
uchar* dptr = dst.ptr(i);
if( !inplace )
memcpy(dptr, src.ptr(i), src.cols * src.elemSize());
ptr = dptr;
}
else
{
subRect.x = i;
Mat(src, subRect).copyTo(row);
ptr = row.ptr();
}
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer.data()) < 0)
return false;
if( CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, ptr, len, buffer.data()) < 0 )
{
ok = false;
break;
}
row = row.reshape(1, dstSub.rows);
row.copyTo(dstSub);
if( !sortRows )
{
Mat dstSub(dst, subRect);
row = row.reshape(1, dstSub.rows);
row.copyTo(dstSub);
row = row.reshape(1, 1);
}
}
}
});
return true;
return ok;
}
#endif
@@ -1185,7 +1192,7 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
}
}
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(const void* pSrc, Ipp32s srcStrideBytes, Ipp32s *pDstIndx, int len, Ipp8u *pBuffer);
static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
@@ -1276,7 +1283,9 @@ void cv::sort( InputArray _src, OutputArray _dst, int flags )
CV_Assert( src.dims <= 2 && src.channels() == 1 );
_dst.createSameSize( src, src.type() );
Mat dst = _dst.getMat();
#if !IPP_DISABLE_SORT
CV_IPP_RUN_FAST(ipp_sort(src, dst, flags));
#endif
static SortFunc tab[CV_DEPTH_MAX] =
{
@@ -1301,7 +1310,9 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
_dst.createSameSize( src, CV_32S );
dst = _dst.getMat();
#if !IPP_DISABLE_SORT
CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags));
#endif
static SortFunc tab[CV_DEPTH_MAX] =
{
@@ -832,7 +832,8 @@ CV_EXPORTS_W Vec3d RQDecomp3x3( InputArray src, OutputArray mtxR, OutputArray mt
@param projMatrix 3x4 input projection matrix P.
@param cameraMatrix Output 3x3 camera intrinsic matrix \f$\cameramatrix{A}\f$.
@param rotMatrix Output 3x3 external rotation matrix R.
@param transVect Output 4x1 translation vector T.
@param transVect Output 4x1 vector representing the camera position in homogeneous coordinates.
To obtain the translation vector, use t = -rotMatrix * transVect[:3]
@param rotMatrixX Optional 3x3 rotation matrix around x-axis.
@param rotMatrixY Optional 3x3 rotation matrix around y-axis.
@param rotMatrixZ Optional 3x3 rotation matrix around z-axis.
+6 -4
View File
@@ -2178,9 +2178,11 @@ with the WARP_RELATIVE_MAP flag :
where values of pixels with non-integer coordinates are computed using one of available
interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps
in \f$map_1\f$ and \f$map_2\f$ respectively, or interleaved floating-point maps of \f$(x,y)\f$ in
\f$map_1\f$, or fixed-point maps created by using #convertMaps. The reason you might want to
convert from floating to fixed-point representations of a map is that they can yield much faster
(\~2x) remapping operations. In the converted case, \f$map_1\f$ contains pairs (cvFloor(x),
\f$map_1\f$, or fixed-point maps created by using #convertMaps. Fixed-point maps
use a more compact representation, which can reduce memory bandwidth and benefit
repeated remap calls that reuse the same map. Performance gains vary by hardware
and are typically modest; measure before converting. In the converted case,
\f$map_1\f$ contains pairs (cvFloor(x),
cvFloor(y)) and \f$map_2\f$ contains indices in a table of interpolation coefficients.
This function cannot operate in-place.
@@ -2189,7 +2191,7 @@ This function cannot operate in-place.
@param dst Destination image. It has the same size as map1 and the same type as src .
@param map1 The first map of either (x,y) points or just x values having the type CV_16SC2 ,
CV_32FC1, or CV_32FC2. See #convertMaps for details on converting a floating point
representation to fixed-point for speed.
representation to fixed-point.
@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map
if map1 is (x,y) points), respectively.
@param interpolation Interpolation method (see #InterpolationFlags). The methods #INTER_AREA
+2 -82
View File
@@ -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)
{
+9 -86
View File
@@ -40,6 +40,7 @@
//
//M*/
#include "precomp.hpp"
#include "hal_replacement.hpp"
namespace cv
{
@@ -1004,19 +1005,8 @@ static void distanceTransform_L1_8U(InputArray _src, OutputArray _dst)
_dst.create( src.size(), CV_8UC1);
Mat dst = _dst.getMat();
#ifdef HAVE_IPP
CV_IPP_CHECK()
{
IppiSize roi = { src.cols, src.rows };
Ipp32s pMetrics[2] = { 1, 2 }; //L1, 3x3 mask
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<uchar>(), (int)dst.step, roi, pMetrics) >= 0)
{
CV_IMPL_ADD(CV_IMPL_IPP);
return;
}
setIppErrorStatus();
}
#endif
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
src.cols, src.rows, CV_8U, cv::DIST_L1, cv::DIST_MASK_3);
distanceATS_L1_8u(src, dst);
}
@@ -1055,53 +1045,8 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
if( maskSize == cv::DIST_MASK_PRECISE )
{
#ifdef HAVE_IPP
CV_IPP_CHECK()
{
#if IPP_DISABLE_PERF_TRUE_DIST_MT
// IPP uses floats, but 4097 cannot be squared into a float
if((cv::getNumThreads()<=1 || (src.total()<(int)(1<<14))) &&
src.rows < 4097 && src.cols < 4097)
#endif
{
IppStatus status;
IppiSize roi = { src.cols, src.rows };
Ipp8u *pBuffer;
int bufSize=0;
status = ippiTrueDistanceTransformGetBufferSize_8u32f_C1R(roi, &bufSize);
if (status>=0)
{
pBuffer = (Ipp8u *)CV_IPP_MALLOC( bufSize );
status = CV_INSTRUMENT_FUN_IPP(ippiTrueDistanceTransform_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, pBuffer);
ippFree( pBuffer );
if (status>=0)
{
// https://github.com/opencv/opencv/issues/24082
// There is probably a rounding issue that leads to non-deterministic behavior
// between runs on positions closer to zeros by x-axis in straight direction.
// As a workaround, we detect the distances that expected to be exact
// number of pixels and round manually.
static const float correctionDiff = 1.0f / (1 << 11);
for (int i = 0; i < dst.rows; ++i)
{
float* row = dst.ptr<float>(i);
for (int j = 0; j < dst.cols; ++j)
{
float rounded = static_cast<float>(cvRound(row[j]));
if (fabs(row[j] - rounded) <= correctionDiff)
row[j] = rounded;
}
}
CV_IMPL_ADD(CV_IMPL_IPP);
return;
}
setIppErrorStatus();
}
}
}
#endif
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_PRECISE);
trueDistTrans( src, dst );
return;
@@ -1121,38 +1066,16 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
{
if( maskSize == cv::DIST_MASK_3 )
{
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
if (!has_int_overflow && CV_IPP_CHECK_COND)
{
IppiSize roi = { src.cols, src.rows };
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_3x3_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
{
CV_IMPL_ADD(CV_IMPL_IPP);
return;
}
setIppErrorStatus();
}
#endif
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_3);
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
distanceTransform_3x3(src, temp, dst, _mask);
}
else
{
#if defined (HAVE_IPP) && (IPP_VERSION_X100 >= 700)
bool has_int_overflow = (int64)src.cols * src.rows >= INT_MAX;
if (!has_int_overflow && CV_IPP_CHECK_COND)
{
IppiSize roi = { src.cols, src.rows };
if (CV_INSTRUMENT_FUN_IPP(ippiDistanceTransform_5x5_8u32f_C1R, src.ptr<uchar>(), (int)src.step, dst.ptr<float>(), (int)dst.step, roi, _mask) >= 0)
{
CV_IMPL_ADD(CV_IMPL_IPP);
return;
}
setIppErrorStatus();
}
#endif
CALL_HAL(distanceTransform, cv_hal_distanceTransform, src.ptr<uchar>(), src.step, dst.ptr<uchar>(), dst.step,
src.cols, src.rows, CV_32F, distType, cv::DIST_MASK_5);
temp.create(size.height + border*2, size.width + border*2, CV_32SC1);
distanceTransform_5x5(src, temp, dst, _mask);
+65 -11
View File
@@ -1067,16 +1067,6 @@ inline int hal_ni_cvtRGBAtoMultipliedRGBA(const uchar * src_data, size_t src_ste
*/
inline int hal_ni_cvtMultipliedRGBAtoRGBA(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
/** @brief Extract Y-plane from YUV 4:2:0 image.
@param src_data Source image data pointer (points to Y plane).
@param src_step Source step.
@param dst_data Destination data pointer.
@param dst_step Destination step.
@param width Image width.
@param height Image height (of the Y plane, not the full YUV image).
*/
inline int hal_ni_cvtColorYUV2Gray(const uchar * src_data, size_t src_step, uchar * dst_data, size_t dst_step, int width, int height) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_cvtBGRtoBGR hal_ni_cvtBGRtoBGR
#define cv_hal_cvtBGRtoBGR5x5 hal_ni_cvtBGRtoBGR5x5
@@ -1110,7 +1100,6 @@ inline int hal_ni_cvtColorYUV2Gray(const uchar * src_data, size_t src_step, ucha
#define cv_hal_cvtOnePlaneBGRtoYUVApprox hal_ni_cvtOnePlaneBGRtoYUVApprox
#define cv_hal_cvtRGBAtoMultipliedRGBA hal_ni_cvtRGBAtoMultipliedRGBA
#define cv_hal_cvtMultipliedRGBAtoRGBA hal_ni_cvtMultipliedRGBAtoRGBA
#define cv_hal_cvtColorYUV2Gray hal_ni_cvtColorYUV2Gray
//! @endcond
/**
@@ -1252,6 +1241,24 @@ inline int hal_ni_threshold_otsu(const uchar* src_data, size_t src_step, uchar*
#define cv_hal_threshold_otsu hal_ni_threshold_otsu
//! @endcond
/**
@brief Calculates the distance to the closest zero pixel for each pixel of the source image
@param src_data Source image (8-bit single-channel) data
@param src_step Source image step
@param dst_data Destination image data
@param dst_step Destination image step
@param width Source image width
@param height Source image height
@param dst_type Type of the destination image (CV_8UC1 or CV_32FC1)
@param dist_type Type of distance (cv::DistanceTypes: DIST_L1, DIST_L2, DIST_C)
@param mask_size Size of the distance transform mask (cv::DistanceTransformMasks: DIST_MASK_3, DIST_MASK_5, DIST_MASK_PRECISE)
*/
inline int hal_ni_distanceTransform(const uchar* src_data, size_t src_step, uchar* dst_data, size_t dst_step, int width, int height, int dst_type, int dist_type, int mask_size) { return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_distanceTransform hal_ni_distanceTransform
//! @endcond
/**
@brief Calculate box filter
@param src_data Source image data
@@ -1531,6 +1538,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 a histogram of a set of arrays
@param src_data Source imgage data
@@ -1551,6 +1579,32 @@ inline int hal_ni_calcHist(const uchar* src_data, size_t src_step, int src_type,
#define cv_hal_calcHist hal_ni_calcHist
//! @endcond
/**
@brief Compares a template against overlapped image regions.
@param src_data Source image (single-channel, CV_8U or CV_32F) data
@param src_step Source image step
@param src_width Source image width
@param src_height Source image height
@param templ_data Template image data (same type as source)
@param templ_step Template image step
@param templ_width Template image width
@param templ_height Template image height
@param result_data Destination map data (single-channel CV_32F, size (src_width-templ_width+1) x (src_height-templ_height+1))
@param result_step Destination map step
@param depth Depth of source and template images (CV_8U or CV_32F)
@param cn Number of channels
@param method Comparison method (cv::TemplateMatchModes)
@sa matchTemplate
*/
inline int hal_ni_matchTemplate(const uchar* src_data, size_t src_step, int src_width, int src_height,
const uchar* templ_data, size_t templ_step, int templ_width, int templ_height,
float* result_data, size_t result_step, int depth, int cn, int method)
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_matchTemplate hal_ni_matchTemplate
//! @endcond
//! @}
#if defined(__clang__)
+16 -130
View File
@@ -1034,135 +1034,6 @@ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method,
}
}
#if defined HAVE_IPP
namespace cv
{
typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*);
static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst, bool normed)
{
CV_INSTRUMENT_REGION_IPP();
IppStatus status;
IppiSize srcRoiSize = {src.cols,src.rows};
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
IppAutoBuffer<Ipp8u> buffer;
int bufSize=0;
int depth = src.depth();
ippimatchTemplate ippiCrossCorrNorm =
depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R:
depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0;
if (ippiCrossCorrNorm==0)
return false;
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid);
if(normed)
funCfg |= ippiNorm;
else
funCfg |= ippiNormNone;
status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
if ( status < 0 )
return false;
buffer.allocate( bufSize );
status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
return status >= 0;
}
static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst)
{
CV_INSTRUMENT_REGION_IPP();
IppStatus status;
IppiSize srcRoiSize = {src.cols,src.rows};
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
IppAutoBuffer<Ipp8u> buffer;
int bufSize=0;
int depth = src.depth();
ippimatchTemplate ippiSqrDistanceNorm =
depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R:
depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0;
if (ippiSqrDistanceNorm==0)
return false;
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid | ippiNormNone);
status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
if ( status < 0 )
return false;
buffer.allocate( bufSize );
status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
dst = cv::max(dst, 0); // handle edge case from rounding in variance computation which can result in negative values
return status >= 0;
}
static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method)
{
CV_INSTRUMENT_REGION_IPP();
if(img.channels() != 1)
return false;
// These functions are not efficient if template size is comparable with image size
if(templ.size().area()*4 > img.size().area())
return false;
// CV_8U SQDIFF/SQDIFF_NORMED suffer from float32 catastrophic cancellation
// in IPP's internal accumulators; fall through to the double-precision path instead.
if(img.depth() == CV_8U && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED))
return false;
if(method == cv::TM_SQDIFF)
{
if(ipp_sqrDistance(img, templ, result))
return true;
}
else if(method == cv::TM_SQDIFF_NORMED)
{
if(ipp_crossCorr(img, templ, result, false))
{
common_matchTemplate(img, templ, result, cv::TM_SQDIFF_NORMED, 1);
return true;
}
}
else if(method == cv::TM_CCORR)
{
if(ipp_crossCorr(img, templ, result, false))
return true;
}
else if(method == cv::TM_CCORR_NORMED)
{
if(ipp_crossCorr(img, templ, result, true))
return true;
}
else if(method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
{
if(ipp_crossCorr(img, templ, result, false))
{
common_matchTemplate(img, templ, result, method, 1);
return true;
}
}
return false;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
@@ -1196,7 +1067,22 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result,
_result.create(corrSize, CV_32F);
Mat result = _result.getMat();
CV_IPP_RUN_FAST(ipp_matchTemplate(img, templ, result, method))
{
int hal_res = cv_hal_matchTemplate(img.data, img.step, img.cols, img.rows,
templ.data, templ.step, templ.cols, templ.rows,
result.ptr<float>(), result.step, depth, cn, method);
if (hal_res == CV_HAL_ERROR_OK)
{
if (method == cv::TM_SQDIFF_NORMED || method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
common_matchTemplate(img, templ, result, method, 1);
return;
}
else if (hal_res != CV_HAL_ERROR_NOT_IMPLEMENTED)
{
CV_Error_(cv::Error::StsInternal,
("HAL implementation matchTemplate ==> cv_hal_matchTemplate returned %d (0x%08x)", hal_res, hal_res));
}
}
bool use64f = (depth == CV_8U) && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED);
Mat result64f;
-136
View File
@@ -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<float>::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 );