Merge pull request #22074 from bwang30:opencv-warpAffine-ippiw

Add warpAffine IPPIW implementation to replace with old version
This commit is contained in:
Alexander Smorkalov 2022-10-04 14:38:00 +03:00 committed by GitHub
commit 8f0edf6a1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2542,6 +2542,127 @@ 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, 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));
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;
#endif
}
#endif
namespace hal {
void warpAffine(int src_type,
@ -2611,6 +2732,8 @@ 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, matM, flags));
if( !(flags & WARP_INVERSE_MAP) )
{
double D = M[0]*M[4] - M[1]*M[3];