Add warpAffine IPPIW implementation protected by ipp NE flag
authorrobin <bin.wang@intel.com>
Tue, 7 Jun 2022 05:31:56 +0000 (13:31 +0800)
committerAlexander Smorkalov <alexander.smorkalov@xperience.ai>
Tue, 4 Oct 2022 05:40:44 +0000 (08:40 +0300)
Signed-off-by: robin <bin.wang@intel.com>
modules/imgproc/src/imgwarp.cpp

index c6dd063..c36c8ce 100644 (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];