cv::Laplacian
authorIlya Lavrenov <ilya.lavrenov@itseez.com>
Sat, 12 Apr 2014 11:40:26 +0000 (15:40 +0400)
committerIlya Lavrenov <ilya.lavrenov@itseez.com>
Mon, 14 Apr 2014 10:34:28 +0000 (14:34 +0400)
modules/core/include/opencv2/core/private.hpp
modules/imgproc/src/deriv.cpp

index 593ee9f..8857fa3 100644 (file)
@@ -230,6 +230,15 @@ static inline IppiSize ippiSize(const cv::Size & _size)
     return size;
 }
 
+static inline IppiBorderType ippiGetBorderType(int borderTypeNI)
+{
+    return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst :
+        borderTypeNI == cv::BORDER_WRAP ? ippBorderWrap :
+        borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl :
+        borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror :
+        borderTypeNI == cv::BORDER_REFLECT ? ippBorderMirrorR : (IppiBorderType)-1;
+}
+
 #else
 #  define IPP_VERSION_X100 0
 #endif
index 1b3e2c4..5d66318 100644 (file)
@@ -577,6 +577,62 @@ void cv::Laplacian( InputArray _src, OutputArray _dst, int ddepth, int ksize,
         ddepth = sdepth;
     _dst.create( _src.size(), CV_MAKETYPE(ddepth, cn) );
 
+#if defined HAVE_IPP && !defined HAVE_IPP_ICV_ONLY
+    if ((ksize == 3 || ksize == 5) && ((borderType & BORDER_ISOLATED) != 0 || !_src.isSubmatrix()) &&
+        ((stype == CV_8UC1 && ddepth == CV_16S) || (ddepth == CV_32F && stype == CV_32FC1)))
+    {
+        int iscale = saturate_cast<int>(scale), idelta = saturate_cast<int>(delta);
+        bool floatScale = std::fabs(scale - iscale) > DBL_EPSILON, needScale = iscale != 1;
+        bool floatDelta = std::fabs(delta - idelta) > DBL_EPSILON, needDelta = delta != 0;
+        int borderTypeNI = borderType & ~BORDER_ISOLATED;
+        Mat src = _src.getMat(), dst = _dst.getMat();
+
+        if (src.data != dst.data)
+        {
+            Ipp32s bufsize;
+            IppStatus status = (IppStatus)-1;
+            IppiSize roisize = { src.cols, src.rows };
+            IppiMaskSize masksize = ksize == 3 ? ippMskSize3x3 : ippMskSize5x5;
+            IppiBorderType borderTypeIpp = ippiGetBorderType(borderTypeNI);
+
+#define IPP_FILTER_LAPLACIAN(ippsrctype, ippdsttype, ippfavor) \
+    do \
+    { \
+        if (borderTypeIpp >= 0 && ippiFilterLaplacianGetBufferSize_##ippfavor##_C1R(roisize, masksize, &bufsize) >= 0) \
+        { \
+            Ipp8u * buffer = ippsMalloc_8u(bufsize); \
+            status = ippiFilterLaplacianBorder_##ippfavor##_C1R((const ippsrctype *)src.data, (int)src.step, (ippdsttype *)dst.data, \
+                                                                (int)dst.step, roisize, masksize, borderTypeIpp, 0, buffer); \
+            ippsFree(buffer); \
+        } \
+    } while ((void)0, 0)
+
+            if (sdepth == CV_8U && ddepth == CV_16S && !floatScale && !floatDelta)
+            {
+                IPP_FILTER_LAPLACIAN(Ipp8u, Ipp16s, 8u16s);
+
+                if (needScale && status >= 0)
+                    status = ippiMulC_16s_C1IRSfs((Ipp16s)iscale, (Ipp16s *)dst.data, (int)dst.step, roisize, 0);
+                if (needDelta && status >= 0)
+                    status = ippiAddC_16s_C1IRSfs((Ipp16s)idelta, (Ipp16s *)dst.data, (int)dst.step, roisize, 0);
+            }
+            else if (sdepth == CV_32F && ddepth == CV_32F)
+            {
+                IPP_FILTER_LAPLACIAN(Ipp32f, Ipp32f, 32f);
+
+                if (needScale && status >= 0)
+                    status = ippiMulC_32f_C1IR((Ipp32f)scale, (Ipp32f *)dst.data, (int)dst.step, roisize);
+                if (needDelta && status >= 0)
+                    status = ippiAddC_32f_C1IR((Ipp32f)delta, (Ipp32f *)dst.data, (int)dst.step, roisize);
+            }
+
+            if (status >= 0)
+                return;
+        }
+    }
+#undef IPP_FILTER_LAPLACIAN
+#endif
+
 #ifdef HAVE_TEGRA_OPTIMIZATION
     if (scale == 1.0 && delta == 0)
     {