diff --git a/modules/imgproc/src/imgwarp.cpp b/modules/imgproc/src/imgwarp.cpp index c6dd063f73be7f8c6fc73edce172ec7b4123d608..c36c8cebf53d694b97294d8dbb24a661e64ec90b 100644 --- a/modules/imgproc/src/imgwarp.cpp +++ b/modules/imgproc/src/imgwarp.cpp @@ -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(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];