Added IPP Pyramid API functions to cv::buildPyramid
authorAlexander Karsakov <alexander.karsakov@itseez.com>
Wed, 16 Apr 2014 12:00:07 +0000 (16:00 +0400)
committerAlexander Karsakov <alexander.karsakov@itseez.com>
Wed, 16 Apr 2014 13:10:20 +0000 (17:10 +0400)
modules/imgproc/perf/perf_pyramids.cpp
modules/imgproc/src/pyramids.cpp

index 1310239..8062297 100644 (file)
@@ -45,8 +45,8 @@ PERF_TEST_P(Size_MatType, pyrUp, testing::Combine(
 }
 
 PERF_TEST_P(Size_MatType, buildPyramid, testing::Combine(
-                testing::Values(sz2160p, sz1080p, sz720p, szVGA, szQVGA, szODD),
-                testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1, CV_32FC3, CV_32FC4)
+                testing::Values(sz1080p, sz720p, szVGA, szQVGA, szODD),
+                testing::Values(CV_8UC1, CV_8UC3, CV_8UC4, CV_16UC1, CV_16UC3, CV_16UC4, CV_32FC1, CV_32FC3, CV_32FC4)
                 )
             )
 {
@@ -64,9 +64,9 @@ PERF_TEST_P(Size_MatType, buildPyramid, testing::Combine(
 
     Mat dst0 = dst[0], dst1 = dst[1], dst2 = dst[2], dst3 = dst[3], dst4 = dst[4];
 
-    SANITY_CHECK(dst0, eps);
-    SANITY_CHECK(dst1, eps);
-    SANITY_CHECK(dst2, eps);
-    SANITY_CHECK(dst3, eps);
-    SANITY_CHECK(dst4, eps);
+    SANITY_CHECK(dst0, eps, ERROR_RELATIVE);
+    SANITY_CHECK(dst1, eps, ERROR_RELATIVE);
+    SANITY_CHECK(dst2, eps, ERROR_RELATIVE);
+    SANITY_CHECK(dst3, eps, ERROR_RELATIVE);
+    SANITY_CHECK(dst4, eps, ERROR_RELATIVE);
 }
index 3f51908..a984f25 100644 (file)
@@ -585,9 +585,9 @@ void cv::pyrUp( InputArray _src, OutputArray _dst, const Size& _dsz, int borderT
         int type = src.type();
         CV_SUPPRESS_DEPRECATED_START
         ippiPyrUp pyrUpFunc = type == CV_8UC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C1R :
-                                  type == CV_8UC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C3R :
-                                  type == CV_32FC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C1R :
-                                  type == CV_32FC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C3R : 0;
+                              type == CV_8UC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_8u_C3R :
+                              type == CV_32FC1 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C1R :
+                              type == CV_32FC3 ? (ippiPyrUp) ippiPyrUp_Gauss5x5_32f_C3R : 0;
         CV_SUPPRESS_DEPRECATED_END
 
         if (pyrUpFunc)
@@ -643,7 +643,96 @@ void cv::buildPyramid( InputArray _src, OutputArrayOfArrays _dst, int maxlevel,
     Mat src = _src.getMat();
     _dst.create( maxlevel + 1, 1, 0 );
     _dst.getMatRef(0) = src;
-    for( int i = 1; i <= maxlevel; i++ )
+
+    int i=1;
+
+#if (defined(HAVE_IPP) && !defined(HAVE_IPP_ICV_ONLY) && IPP_VERSION_X100 >= 801)
+    bool isolated = (borderType & BORDER_ISOLATED) != 0;
+    int borderTypeNI = borderType & ~BORDER_ISOLATED;
+    if (borderTypeNI == BORDER_DEFAULT && (!src.isSubmatrix() || isolated))
+    {
+        typedef IppStatus (CV_STDCALL * ippiPyramidLayerDownInitAlloc)(void** ppState, IppiSize srcRoi, Ipp32f rate, void* pKernel, int kerSize, int mode);
+        typedef IppStatus (CV_STDCALL * ippiPyramidLayerDown)(void* pSrc, int srcStep, IppiSize srcRoiSize, void* pDst, int dstStep, IppiSize dstRoiSize, void* pState);
+        typedef IppStatus (CV_STDCALL * ippiPyramidLayerDownFree)(void* pState);
+
+        int type = src.type();
+        int depth = src.depth();
+        ippiPyramidLayerDownInitAlloc pyrInitAllocFunc = 0;
+        ippiPyramidLayerDown pyrDownFunc = 0;
+        ippiPyramidLayerDownFree pyrFreeFunc = 0;
+
+        if (type == CV_8UC1)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_8u_C1R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_8u_C1R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_8u_C1R;
+        } else if (type == CV_8UC3)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_8u_C3R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_8u_C3R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_8u_C3R;
+        } else if (type == CV_16UC1)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_16u_C1R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_16u_C1R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_16u_C1R;
+        } else if (type == CV_16UC3)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_16u_C3R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_16u_C3R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_16u_C3R;
+        } else if (type == CV_32FC1)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_32f_C1R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_32f_C1R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_32f_C1R;
+        } else if (type == CV_32FC3)
+        {
+            pyrInitAllocFunc = (ippiPyramidLayerDownInitAlloc) ippiPyramidLayerDownInitAlloc_32f_C3R;
+            pyrDownFunc = (ippiPyramidLayerDown) ippiPyramidLayerDown_32f_C3R;
+            pyrFreeFunc = (ippiPyramidLayerDownFree) ippiPyramidLayerDownFree_32f_C3R;
+        }
+
+        if (pyrInitAllocFunc && pyrDownFunc && pyrFreeFunc)
+        {
+            float rate = 2.f;
+            IppiSize srcRoi = { src.cols, src.rows };
+            IppiPyramid *gPyr;
+            IppStatus ok = ippiPyramidInitAlloc(&gPyr, maxlevel + 1, srcRoi, rate);
+
+            Ipp16s iKernel[5] = { 1, 4, 6, 4, 1 };
+            Ipp32f fKernel[5] = { 1.f, 4.f, 6.f, 4.f, 1.f };
+            void* kernel = depth >= CV_32F ? (void*) fKernel : (void*) iKernel;
+
+            if (ok >= 0) ok = pyrInitAllocFunc((void**) &(gPyr->pState), srcRoi, rate, kernel, 5, IPPI_INTER_LINEAR);
+            if (ok >= 0)
+            {
+                gPyr->pImage[0] = src.data;
+                gPyr->pStep[0] = (int) src.step;
+                gPyr->pRoi[0] = srcRoi;
+                for( ; i <= maxlevel; i++ )
+                {
+                    IppiSize dstRoi;
+                    ok = ippiGetPyramidDownROI(gPyr->pRoi[i-1], &dstRoi, rate);
+                    Mat& dst = _dst.getMatRef(i);
+                    dst.create(Size(dstRoi.width, dstRoi.height), type);
+                    gPyr->pImage[i] = dst.data;
+                    gPyr->pStep[i] = (int) dst.step;
+                    gPyr->pRoi[i] = dstRoi;
+
+                    if (ok >= 0) ok = pyrDownFunc(gPyr->pImage[i-1], gPyr->pStep[i-1], gPyr->pRoi[i-1],
+                                                  gPyr->pImage[i], gPyr->pStep[i], gPyr->pRoi[i], gPyr->pState);
+
+                    if (ok < 0)
+                        break;
+                }
+                pyrFreeFunc(gPyr->pState);
+            }
+            ippiPyramidFree(gPyr);
+        }
+    }
+#endif
+    for( ; i <= maxlevel; i++ )
         pyrDown( _dst.getMatRef(i-1), _dst.getMatRef(i), Size(), borderType );
 }