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

Merge branch 4.x

This commit is contained in:
Alexander Smorkalov
2025-07-17 18:23:51 +03:00
140 changed files with 2891 additions and 1208 deletions
+16
View File
@@ -796,6 +796,22 @@ void cv::distanceTransform( InputArray _src, OutputArray _dst, OutputArray _labe
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;
}
+5 -5
View File
@@ -271,20 +271,20 @@ static LineSegmentIntersection parallelInt( Point2f a, Point2f b, Point2f c, Poi
static LineSegmentIntersection intersectLineSegments( Point2f a, Point2f b, Point2f c,
Point2f d, Point2f& p, Point2f& q )
{
double denom = (a.x - b.x) * (double)(d.y - c.y) - (a.y - b.y) * (double)(d.x - c.x);
double denom = ((double)a.x - b.x) * ((double)d.y - c.y) - ((double)a.y - b.y) * ((double)d.x - c.x);
// If denom is zero, then segments are parallel: handle separately.
if( denom == 0. )
return parallelInt(a, b, c, d, p, q);
double num = (d.y - a.y) * (double)(a.x - c.x) + (a.x - d.x) * (double)(a.y - c.y);
double num = ((double)d.y - a.y) * ((double)a.x - c.x) + ((double)a.x - d.x) * ((double)a.y - c.y);
double s = num / denom;
num = (b.y - a.y) * (double)(a.x - c.x) + (c.y - a.y) * (double)(b.x - a.x);
num = ((double)b.y - a.y) * ((double)a.x - c.x) + ((double)c.y - a.y) * ((double)b.x - a.x);
double t = num / denom;
p.x = (float)(a.x + s*(b.x - a.x));
p.y = (float)(a.y + s*(b.y - a.y));
p.x = (float)(a.x + s*((double)b.x - a.x));
p.y = (float)(a.y + s*((double)b.y - a.y));
q = p;
return s < 0. || s > 1. || t < 0. || t > 1. ? LS_NO_INTERSECTION :
-516
View File
@@ -63,67 +63,6 @@ using namespace cv;
namespace cv
{
#if defined (HAVE_IPP) && (!IPP_DISABLE_WARPAFFINE || !IPP_DISABLE_WARPPERSPECTIVE || !IPP_DISABLE_REMAP)
typedef IppStatus (CV_STDCALL* ippiSetFunc)(const void*, void *, int, IppiSize);
template <int channels, typename Type>
bool IPPSetSimple(cv::Scalar value, void *dataPointer, int step, IppiSize &size, ippiSetFunc func)
{
CV_INSTRUMENT_REGION_IPP();
Type values[channels];
for( int i = 0; i < channels; i++ )
values[i] = saturate_cast<Type>(value[i]);
return func(values, dataPointer, step, size) >= 0;
}
static bool IPPSet(const cv::Scalar &value, void *dataPointer, int step, IppiSize &size, int channels, int depth)
{
CV_INSTRUMENT_REGION_IPP();
if( channels == 1 )
{
switch( depth )
{
case CV_8U:
return CV_INSTRUMENT_FUN_IPP(ippiSet_8u_C1R, saturate_cast<Ipp8u>(value[0]), (Ipp8u *)dataPointer, step, size) >= 0;
case CV_16U:
return CV_INSTRUMENT_FUN_IPP(ippiSet_16u_C1R, saturate_cast<Ipp16u>(value[0]), (Ipp16u *)dataPointer, step, size) >= 0;
case CV_32F:
return CV_INSTRUMENT_FUN_IPP(ippiSet_32f_C1R, saturate_cast<Ipp32f>(value[0]), (Ipp32f *)dataPointer, step, size) >= 0;
}
}
else
{
if( channels == 3 )
{
switch( depth )
{
case CV_8U:
return IPPSetSimple<3, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C3R);
case CV_16U:
return IPPSetSimple<3, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C3R);
case CV_32F:
return IPPSetSimple<3, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C3R);
}
}
else if( channels == 4 )
{
switch( depth )
{
case CV_8U:
return IPPSetSimple<4, Ipp8u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_8u_C4R);
case CV_16U:
return IPPSetSimple<4, Ipp16u>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_16u_C4R);
case CV_32F:
return IPPSetSimple<4, Ipp32f>(value, dataPointer, step, size, (ippiSetFunc)ippiSet_32f_C4R);
}
}
}
return false;
}
#endif
/************** interpolation formulas and tables ***************/
const int INTER_REMAP_COEF_BITS=15;
@@ -1434,58 +1373,6 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input
#endif
#if defined HAVE_IPP && !IPP_DISABLE_REMAP
typedef IppStatus (CV_STDCALL * ippiRemap)(const void * pSrc, IppiSize srcSize, int srcStep, IppiRect srcRoi,
const Ipp32f* pxMap, int xMapStep, const Ipp32f* pyMap, int yMapStep,
void * pDst, int dstStep, IppiSize dstRoiSize, int interpolation);
class IPPRemapInvoker :
public ParallelLoopBody
{
public:
IPPRemapInvoker(Mat & _src, Mat & _dst, Mat & _xmap, Mat & _ymap, ippiRemap _ippFunc,
int _ippInterpolation, int _borderType, const Scalar & _borderValue, bool * _ok) :
ParallelLoopBody(), src(_src), dst(_dst), map1(_xmap), map2(_ymap), ippFunc(_ippFunc),
ippInterpolation(_ippInterpolation), borderType(_borderType), borderValue(_borderValue), ok(_ok)
{
*ok = true;
}
virtual void operator() (const Range & range) const
{
IppiRect srcRoiRect = { 0, 0, src.cols, src.rows };
Mat dstRoi = dst.rowRange(range);
IppiSize dstRoiSize = ippiSize(dstRoi.size());
int type = dst.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
if (borderType == BORDER_CONSTANT &&
!IPPSet(borderValue, dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, cn, depth))
{
*ok = false;
return;
}
if (CV_INSTRUMENT_FUN_IPP(ippFunc, src.ptr(), ippiSize(src.size()), (int)src.step, srcRoiRect,
map1.ptr<Ipp32f>(), (int)map1.step, map2.ptr<Ipp32f>(), (int)map2.step,
dstRoi.ptr(), (int)dstRoi.step, dstRoiSize, ippInterpolation) < 0)
*ok = false;
else
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
}
}
private:
Mat & src, & dst, & map1, & map2;
ippiRemap ippFunc;
int ippInterpolation, borderType;
Scalar borderValue;
bool * ok;
};
#endif
}
void cv::remap( InputArray _src, OutputArray _dst,
@@ -1652,47 +1539,6 @@ void cv::remap( InputArray _src, OutputArray _dst,
}
}
#if defined HAVE_IPP && !IPP_DISABLE_REMAP
CV_IPP_CHECK()
{
if ((interpolation == INTER_LINEAR || interpolation == INTER_CUBIC || interpolation == INTER_NEAREST) &&
map1.type() == CV_32FC1 && map2.type() == CV_32FC1 &&
(borderType == BORDER_CONSTANT || borderType == BORDER_TRANSPARENT))
{
int ippInterpolation =
interpolation == INTER_NEAREST ? IPPI_INTER_NN :
interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR : IPPI_INTER_CUBIC;
ippiRemap ippFunc =
type == CV_8UC1 ? (ippiRemap)ippiRemap_8u_C1R :
type == CV_8UC3 ? (ippiRemap)ippiRemap_8u_C3R :
type == CV_8UC4 ? (ippiRemap)ippiRemap_8u_C4R :
type == CV_16UC1 ? (ippiRemap)ippiRemap_16u_C1R :
type == CV_16UC3 ? (ippiRemap)ippiRemap_16u_C3R :
type == CV_16UC4 ? (ippiRemap)ippiRemap_16u_C4R :
type == CV_32FC1 ? (ippiRemap)ippiRemap_32f_C1R :
type == CV_32FC3 ? (ippiRemap)ippiRemap_32f_C3R :
type == CV_32FC4 ? (ippiRemap)ippiRemap_32f_C4R : 0;
if (ippFunc)
{
bool ok;
IPPRemapInvoker invoker(src, dst, map1, map2, ippFunc, ippInterpolation,
borderType, borderValue, &ok);
Range range(0, dst.rows);
parallel_for_(range, invoker, dst.total() / (double)(1 << 16));
if (ok)
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
return;
}
setIppErrorStatus();
}
}
}
#endif
RemapNNFunc nnfunc = 0;
RemapFunc ifunc = 0;
const void* ctab = 0;
@@ -2188,62 +2034,6 @@ private:
const double *M;
};
#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPAFFINE
typedef IppStatus (CV_STDCALL* ippiWarpAffineBackFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [2][3], int);
class IPPWarpAffineInvoker :
public ParallelLoopBody
{
public:
IPPWarpAffineInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[2][3], int &_interpolation, int _borderType,
const Scalar &_borderValue, ippiWarpAffineBackFunc _func, bool *_ok) :
ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs),
borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok)
{
*ok = true;
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
IppiSize srcsize = { src.cols, src.rows };
IppiRect srcroi = { 0, 0, src.cols, src.rows };
IppiRect dstroi = { 0, range.start, dst.cols, range.end - range.start };
int cnn = src.channels();
if( borderType == BORDER_CONSTANT )
{
IppiSize setSize = { dst.cols, range.end - range.start };
void *dataPointer = dst.ptr(range.start);
if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) )
{
*ok = false;
return;
}
}
// Aug 2013: problem in IPP 7.1, 8.0 : sometimes function return ippStsCoeffErr
IppStatus status = CV_INSTRUMENT_FUN_IPP(func,( src.ptr(), srcsize, (int)src.step[0], srcroi, dst.ptr(),
(int)dst.step[0], dstroi, coeffs, mode ));
if( status < 0)
*ok = false;
else
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
}
}
private:
Mat &src;
Mat &dst;
int mode;
double (&coeffs)[2][3];
int borderType;
Scalar borderValue;
ippiWarpAffineBackFunc func;
bool *ok;
const IPPWarpAffineInvoker& operator= (const IPPWarpAffineInvoker&);
};
#endif
#ifdef HAVE_OPENCL
enum { OCL_OP_PERSPECTIVE = 1, OCL_OP_AFFINE = 0 };
@@ -2435,132 +2225,6 @@ static bool ocl_warpTransform(InputArray _src, OutputArray _dst, InputArray _M0,
#endif
#ifdef HAVE_IPP
#define IPP_WARPAFFINE_PARALLEL 1
#ifdef HAVE_IPP_IW
class ipp_warpAffineParallel: public ParallelLoopBody
{
public:
ipp_warpAffineParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, IppiInterpolationType _inter, double (&_coeffs)[2][3], ::ipp::IwiBorderType _borderType, IwTransDirection _iwTransDirection, bool *_ok):m_src(src), m_dst(dst)
{
pOk = _ok;
inter = _inter;
borderType = _borderType;
iwTransDirection = _iwTransDirection;
for( int i = 0; i < 2; i++ )
for( int j = 0; j < 3; j++ )
coeffs[i][j] = _coeffs[i][j];
*pOk = true;
}
~ipp_warpAffineParallel() {}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
CV_INSTRUMENT_REGION_IPP();
if(*pOk == false)
return;
try
{
::ipp::IwiTile tile = ::ipp::IwiRoi(0, range.start, m_dst.m_size.width, range.end - range.start);
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, m_src, m_dst, coeffs, iwTransDirection, inter, ::ipp::IwiWarpAffineParams(), borderType, tile);
}
catch(const ::ipp::IwException &)
{
*pOk = false;
return;
}
}
private:
::ipp::IwiImage &m_src;
::ipp::IwiImage &m_dst;
IppiInterpolationType inter;
double coeffs[2][3];
::ipp::IwiBorderType borderType;
IwTransDirection iwTransDirection;
bool *pOk;
const ipp_warpAffineParallel& operator= (const ipp_warpAffineParallel&);
};
#endif
static bool ipp_warpAffine( InputArray _src, OutputArray _dst, int interpolation, int borderType, const Scalar & borderValue, InputArray _M, int flags )
{
#ifdef HAVE_IPP_IW
CV_INSTRUMENT_REGION_IPP();
if (!cv::ipp::useIPP_NotExact())
return false;
IppiInterpolationType ippInter = ippiGetInterpolation(interpolation);
if((int)ippInter < 0)
return false;
// Acquire data and begin processing
try
{
Mat src = _src.getMat();
Mat dst = _dst.getMat();
::ipp::IwiImage iwSrc = ippiGetImage(src);
::ipp::IwiImage iwDst = ippiGetImage(dst);
::ipp::IwiBorderType ippBorder(ippiGetBorderType(borderType), ippiGetValue(borderValue));
IwTransDirection iwTransDirection;
if(!ippBorder)
return false;
if( !(flags & WARP_INVERSE_MAP) )
iwTransDirection = iwTransForward;
else
iwTransDirection = iwTransInverse;
Mat M = _M.getMat();
double coeffs[2][3];
for( int i = 0; i < 2; i++ )
for( int j = 0; j < 3; j++ )
coeffs[i][j] = M.at<double>(i, j);
const int threads = ippiSuggestThreadsNum(iwDst, 2);
if(IPP_WARPAFFINE_PARALLEL && threads > 1)
{
bool ok = true;
Range range(0, (int)iwDst.m_size.height);
ipp_warpAffineParallel invoker(iwSrc, iwDst, ippInter, coeffs, ippBorder, iwTransDirection, &ok);
if(!ok)
return false;
parallel_for_(range, invoker, threads*4);
if(!ok)
return false;
} else {
CV_INSTRUMENT_FUN_IPP(::ipp::iwiWarpAffine, iwSrc, iwDst, coeffs, iwTransDirection, ippInter, ::ipp::IwiWarpAffineParams(), ippBorder);
}
}
catch (const ::ipp::IwException &)
{
return false;
}
return true;
#else
CV_UNUSED(_src); CV_UNUSED(_dst); CV_UNUSED(interpolation);
CV_UNUSED(borderType); CV_UNUSED(borderValue); CV_UNUSED(_M); CV_UNUSED(flags);
return false;
#endif
}
#endif
namespace hal {
static void warpAffine(int src_type,
@@ -2812,8 +2476,6 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 2 && M0.cols == 3 );
M0.convertTo(matM, matM.type());
CV_IPP_RUN_FAST(ipp_warpAffine(src, dst, interpolation, borderType, borderValue, matM, flags));
if( !(flags & WARP_INVERSE_MAP) )
{
double D = M[0]*M[4] - M[1]*M[3];
@@ -2826,70 +2488,6 @@ void cv::warpAffine( InputArray _src, OutputArray _dst,
M[2] = b1; M[5] = b2;
}
#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPAFFINE
CV_IPP_CHECK()
{
int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
if( ( depth == CV_8U || depth == CV_16U || depth == CV_32F ) &&
( cn == 1 || cn == 3 || cn == 4 ) &&
( interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC) &&
( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT) )
{
ippiWarpAffineBackFunc ippFunc = 0;
if ((flags & WARP_INVERSE_MAP) != 0)
{
ippFunc =
type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C1R :
type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C3R :
type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_8u_C4R :
type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C1R :
type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C3R :
type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_16u_C4R :
type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C1R :
type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C3R :
type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffineBack_32f_C4R :
0;
}
else
{
ippFunc =
type == CV_8UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C1R :
type == CV_8UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C3R :
type == CV_8UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_8u_C4R :
type == CV_16UC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C1R :
type == CV_16UC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C3R :
type == CV_16UC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_16u_C4R :
type == CV_32FC1 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C1R :
type == CV_32FC3 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C3R :
type == CV_32FC4 ? (ippiWarpAffineBackFunc)ippiWarpAffine_32f_C4R :
0;
}
int mode =
interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR :
interpolation == INTER_NEAREST ? IPPI_INTER_NN :
interpolation == INTER_CUBIC ? IPPI_INTER_CUBIC :
0;
CV_Assert(mode && ippFunc);
double coeffs[2][3];
for( int i = 0; i < 2; i++ )
for( int j = 0; j < 3; j++ )
coeffs[i][j] = matM.at<double>(i, j);
bool ok;
Range range(0, dst.rows);
IPPWarpAffineInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok);
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
if( ok )
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
return;
}
setIppErrorStatus();
}
}
#endif
hal::warpAffine(src.type(), src.data, src.step, src.cols, src.rows, dst.data, dst.step, dst.cols, dst.rows,
M, interpolation, borderType, borderValue.val, hint);
}
@@ -3212,61 +2810,6 @@ private:
Scalar borderValue;
};
#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPPERSPECTIVE
typedef IppStatus (CV_STDCALL* ippiWarpPerspectiveFunc)(const void*, IppiSize, int, IppiRect, void *, int, IppiRect, double [3][3], int);
class IPPWarpPerspectiveInvoker :
public ParallelLoopBody
{
public:
IPPWarpPerspectiveInvoker(Mat &_src, Mat &_dst, double (&_coeffs)[3][3], int &_interpolation,
int &_borderType, const Scalar &_borderValue, ippiWarpPerspectiveFunc _func, bool *_ok) :
ParallelLoopBody(), src(_src), dst(_dst), mode(_interpolation), coeffs(_coeffs),
borderType(_borderType), borderValue(_borderValue), func(_func), ok(_ok)
{
*ok = true;
}
virtual void operator() (const Range& range) const CV_OVERRIDE
{
IppiSize srcsize = {src.cols, src.rows};
IppiRect srcroi = {0, 0, src.cols, src.rows};
IppiRect dstroi = {0, range.start, dst.cols, range.end - range.start};
int cnn = src.channels();
if( borderType == BORDER_CONSTANT )
{
IppiSize setSize = {dst.cols, range.end - range.start};
void *dataPointer = dst.ptr(range.start);
if( !IPPSet( borderValue, dataPointer, (int)dst.step[0], setSize, cnn, src.depth() ) )
{
*ok = false;
return;
}
}
IppStatus status = CV_INSTRUMENT_FUN_IPP(func,(src.ptr();, srcsize, (int)src.step[0], srcroi, dst.ptr(), (int)dst.step[0], dstroi, coeffs, mode));
if (status != ippStsNoErr)
*ok = false;
else
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
}
}
private:
Mat &src;
Mat &dst;
int mode;
double (&coeffs)[3][3];
int borderType;
const Scalar borderValue;
ippiWarpPerspectiveFunc func;
bool *ok;
const IPPWarpPerspectiveInvoker& operator= (const IPPWarpPerspectiveInvoker&);
};
#endif
namespace hal {
static void warpPerspective(int src_type,
@@ -3489,65 +3032,6 @@ void cv::warpPerspective( InputArray _src, OutputArray _dst, InputArray _M0,
CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3 );
M0.convertTo(matM, matM.type());
#if defined (HAVE_IPP) && IPP_VERSION_X100 >= 810 && !IPP_DISABLE_WARPPERSPECTIVE
CV_IPP_CHECK()
{
int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);
if( (depth == CV_8U || depth == CV_16U || depth == CV_32F) &&
(cn == 1 || cn == 3 || cn == 4) &&
( borderType == cv::BORDER_TRANSPARENT || borderType == cv::BORDER_CONSTANT ) &&
(interpolation == INTER_NEAREST || interpolation == INTER_LINEAR || interpolation == INTER_CUBIC))
{
ippiWarpPerspectiveFunc ippFunc = 0;
if ((flags & WARP_INVERSE_MAP) != 0)
{
ippFunc = type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C1R :
type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C3R :
type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_8u_C4R :
type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C1R :
type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C3R :
type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_16u_C4R :
type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C1R :
type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C3R :
type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspectiveBack_32f_C4R : 0;
}
else
{
ippFunc = type == CV_8UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C1R :
type == CV_8UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C3R :
type == CV_8UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_8u_C4R :
type == CV_16UC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C1R :
type == CV_16UC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C3R :
type == CV_16UC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_16u_C4R :
type == CV_32FC1 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C1R :
type == CV_32FC3 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C3R :
type == CV_32FC4 ? (ippiWarpPerspectiveFunc)ippiWarpPerspective_32f_C4R : 0;
}
int mode =
interpolation == INTER_NEAREST ? IPPI_INTER_NN :
interpolation == INTER_LINEAR ? IPPI_INTER_LINEAR :
interpolation == INTER_CUBIC ? IPPI_INTER_CUBIC : 0;
CV_Assert(mode && ippFunc);
double coeffs[3][3];
for( int i = 0; i < 3; i++ )
for( int j = 0; j < 3; j++ )
coeffs[i][j] = matM.at<double>(i, j);
bool ok;
Range range(0, dst.rows);
IPPWarpPerspectiveInvoker invoker(src, dst, coeffs, mode, borderType, borderValue, ippFunc, &ok);
parallel_for_(range, invoker, dst.total()/(double)(1<<16));
if( ok )
{
CV_IMPL_ADD(CV_IMPL_IPP|CV_IMPL_MT);
return;
}
setIppErrorStatus();
}
}
#endif
if( !(flags & WARP_INVERSE_MAP) )
invert(matM, matM);
+4
View File
@@ -1076,6 +1076,10 @@ void LineSegmentDetectorImpl::drawSegments(InputOutputArray _image, InputArray l
}
Mat _lines = lines.getMat();
if (_lines.empty())
{
return;
}
const int N = _lines.checkVector(4);
CV_Assert(_lines.depth() == CV_32F || _lines.depth() == CV_32S);
+16 -1
View File
@@ -138,7 +138,7 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor)
int r = 0, c = 0;
double inv_r2 = 0;
CV_Assert( shape == MORPH_RECT || shape == MORPH_CROSS || shape == MORPH_ELLIPSE );
CV_Assert( shape == MORPH_RECT || shape == MORPH_CROSS || shape == MORPH_ELLIPSE || shape == MORPH_DIAMOND );
anchor = normalizeAnchor(anchor, ksize);
@@ -151,6 +151,11 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor)
c = ksize.width/2;
inv_r2 = r ? 1./((double)r*r) : 0;
}
else if( shape == MORPH_DIAMOND )
{
r = ksize.height/2;
c = ksize.width/2;
}
Mat elem(ksize, CV_8U);
@@ -163,6 +168,16 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor)
j2 = ksize.width;
else if( shape == MORPH_CROSS )
j1 = anchor.x, j2 = j1 + 1;
else if( shape == MORPH_DIAMOND )
{
int dy = std::abs(i - r);
if( dy <= r )
{
int dx = r - dy;
j1 = std::max( c - dx, 0 );
j2 = std::min( c + dx + 1, ksize.width );
}
}
else
{
int dy = i - r;
+43 -4
View File
@@ -38,6 +38,7 @@
#include "precomp.hpp"
#include <vector>
#include "opencv2/core/hal/intrin.hpp"
namespace cv
{
@@ -614,8 +615,27 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
double* const wc = _wc.data();
double coeff0 = 2.0 * CV_PI / (double)(cols - 1), coeff1 = 2.0 * CV_PI / (double)(rows - 1);
for(int j = 0; j < cols; j++)
wc[j] = 0.5 * (1.0 - cos(coeff0 * j));
int c = 0;
#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F
const int nlanes32 = VTraits<v_float32>::vlanes();
const int nlanes64 = VTraits<v_float64>::vlanes();
const int max_nlanes = VTraits<v_float64>::max_nlanes;
std::array<double, max_nlanes> index;
std::iota(index.data(), index.data()+max_nlanes, 0.f);
v_float64 vindex = vx_load(index.data());
v_float64 delta = vx_setall_f64(VTraits<v_float64>::vlanes());
v_float64 vcoeff0 = vx_setall_f64(coeff0);
v_float64 one = vx_setall_f64(1.f);
v_float64 half = vx_setall_f64(0.5f);
for (; c <= cols - nlanes64; c += nlanes64)
{
v_float64 v = v_mul(half, v_sub(one, v_cos(v_mul(vcoeff0, vindex))));
vx_store(wc + c, v);
vindex = v_add(vindex, delta);
}
#endif
for(; c < cols; c++)
wc[c] = 0.5 * (1.0 - cos(coeff0 * c));
if(dst.depth() == CV_32F)
{
@@ -623,7 +643,17 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
{
float* dstData = dst.ptr<float>(i);
double wr = 0.5 * (1.0 - cos(coeff1 * i));
for(int j = 0; j < cols; j++)
int j = 0;
#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F
v_float64 vwr = vx_setall_f64(wr);
for (; j <= cols - nlanes32; j += nlanes32)
{
v_float64 v0 = v_mul(vwr, vx_load(wc + j));
v_float64 v1 = v_mul(vwr, vx_load(wc + j + nlanes64));
vx_store(dstData + j, v_cvt_f32(v0, v1));
}
#endif
for(; j < cols; j++)
dstData[j] = (float)(wr * wc[j]);
}
}
@@ -633,7 +663,16 @@ void cv::createHanningWindow(OutputArray _dst, cv::Size winSize, int type)
{
double* dstData = dst.ptr<double>(i);
double wr = 0.5 * (1.0 - cos(coeff1 * i));
for(int j = 0; j < cols; j++)
int j = 0;
#if CV_SIMD_64F || CV_SIMD_SCALABLE_64F
v_float64 vwr = vx_setall_f64(wr);
for (; j <= cols - nlanes64; j += nlanes64)
{
v_float64 v = v_mul(vwr, vx_load(wc + j));
vx_store(dstData + j, v);
}
#endif
for(; j < cols; j++)
dstData[j] = wr * wc[j];
}
}
+7 -3
View File
@@ -850,7 +850,8 @@ static void matchTemplateMask( InputArray _img, InputArray _templ, OutputArray _
// CCorr(I', T') = CCorr(I, T'*M) - sum(T'*M)/sum(M)*CCorr(I, M)
// It does not matter what to use Mat/MatExpr, it should be evaluated to perform assign subtraction
Mat temp_res = img_mask_corr.mul(sum(templx_mask).div(mask_sum));
Mat temp_res;
multiply(img_mask_corr, sum(templx_mask).div(mask_sum), temp_res);
if (img.channels() == 1)
{
result -= temp_res;
@@ -881,8 +882,11 @@ static void matchTemplateMask( InputArray _img, InputArray _templ, OutputArray _
Mat img_mask2_corr(corrSize, img.type());
crossCorr(img2, mask2, norm_imgx, Point(0,0), 0, 0);
crossCorr(img, mask2, img_mask2_corr, Point(0,0), 0, 0);
temp_res = img_mask_corr.mul(Scalar(1.0, 1.0, 1.0, 1.0).div(mask_sum))
.mul(img_mask_corr.mul(mask2_sum.div(mask_sum)) - 2 * img_mask2_corr);
Mat temp_res1;
multiply(img_mask_corr, Scalar(1.0, 1.0, 1.0, 1.0).div(mask_sum), temp_res1);
Mat temp_res2;
multiply(img_mask_corr, mask2_sum.div(mask_sum), temp_res2);
temp_res = temp_res1.mul(temp_res2 - 2 * img_mask2_corr);
if (img.channels() == 1)
{
norm_imgx += temp_res;