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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user