Some changes in erosion and dilation functions
authorkdrobnyh <klim.drobnyh@gmail.com>
Tue, 30 Jul 2013 11:13:04 +0000 (15:13 +0400)
committerkdrobnyh <klim.drobnyh@gmail.com>
Tue, 30 Jul 2013 11:13:04 +0000 (15:13 +0400)
modules/imgproc/src/morph.cpp

index 0567c48..df3f04b 100644 (file)
@@ -1137,380 +1137,152 @@ private:
 };
 
 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
-static bool IPPDilateReplicate(const Mat &src, Mat &dst, const Mat &kernel, const Point &anchor)
+static bool IPPMorphReplicate(int &op, const Mat &src, Mat &dst, const Mat &kernel, const Point &anchor)
 {
-       int cnn = src.channels();
-       switch( src.depth() )
+       int type = src.type();
+       const Mat* _src = &src;
+       Mat temp;
+       if( src.data == dst.data )
        {
-       case CV_8U:
+               src.copyTo(temp);
+               _src = &temp;
+       }
+       //DEPRECATED. Allocates and initializes morphology state structure for erosion or dilation operation.
+       typedef IppStatus (CV_STDCALL* ippiMorphologyInitAllocFunc)(int, const void*, IppiSize, IppiPoint, IppiMorphState **);
+       ippiMorphologyInitAllocFunc ippInitAllocFunc = 
+               type == CV_8UC1 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C1R : 
+               type == CV_8UC3 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C3R : 
+               type == CV_8UC4 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_8u_C4R : 
+               type == CV_32FC1 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C1R : 
+               type == CV_32FC3 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C3R :
+               type == CV_32FC4 ? (ippiMorphologyInitAllocFunc)ippiMorphologyInitAlloc_32f_C4R :
+               0;
+       typedef IppStatus (CV_STDCALL* ippiMorphologyBorderReplicateFunc)(const void*, int, void *, int, IppiSize, IppiBorderType, IppiMorphState *);
+       ippiMorphologyBorderReplicateFunc ippFunc = 0;
+       switch( op )
+       {
+       case MORPH_DILATE:
                {
-                       switch( cnn ) 
-                       {
-                       case 1:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C1( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C1R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C1R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_8u_C1R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 3:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C3( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C3R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C3R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_8u_C3R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 4:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C4( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C4R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C4R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_8u_C4R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       }
-                       break;
+                       ippFunc = 
+                               type == CV_8UC1 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C1R : 
+                               type == CV_8UC3 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C3R : 
+                               type == CV_8UC4 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_8u_C4R : 
+                               type == CV_32FC1 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C1R :  
+                               type == CV_32FC3 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C3R :  
+                               type == CV_32FC4 ? (ippiMorphologyBorderReplicateFunc)ippiDilateBorderReplicate_32f_C4R :  
+                               0;
+               break;
                }
-       case CV_32F:
+       case MORPH_ERODE:
                {
-                       switch( cnn )
-                       {
-                       case 1:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C1( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C1R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C1R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_32f_C1R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 3:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C3( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C3R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C3R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_32f_C3R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 4:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C4( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C4R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C4R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiDilateBorderReplicate_32f_C4R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       }
-                       break;
+                       ippFunc = 
+                               type == CV_8UC1 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C1R : 
+                               type == CV_8UC3 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C3R : 
+                               type == CV_8UC4 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_8u_C4R : 
+                               type == CV_32FC1 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C1R :  
+                               type == CV_32FC3 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C3R :  
+                               type == CV_32FC4 ? (ippiMorphologyBorderReplicateFunc)ippiErodeBorderReplicate_32f_C4R :  
+                               0;
+               break;
                }
        }
+       if( ippFunc && ippInitAllocFunc)
+       {
+               IppiMorphState* pState;
+               IppiSize roiSize = {src.cols, src.rows};
+               IppiSize kernelSize = {kernel.cols, kernel.rows};
+               IppiPoint point = {anchor.x, anchor.y};
+               if( ippInitAllocFunc( roiSize.width, kernel.data, kernelSize, point, &pState ) < 0 )
+               {
+                       return false;
+               }
+               if( ippFunc( _src->data, _src->step[0],  dst.data, dst.step[0], roiSize, ippBorderRepl, pState ) < 0 )
+               {
+                       ippiMorphologyFree(pState);
+                       return false;
+               }
+               ippiMorphologyFree(pState);
+               return true;
+       }
        return false;
 }
 
-static bool IPPErodeReplicate(const Mat &src, Mat &dst, const Mat &kernel, const Point &anchor)
+static bool IPPMorphOp(int &op, InputArray &_src, OutputArray &_dst,
+       InputArray &_kernel,
+       const Point &anchor, int &iterations,
+       int &borderType, const Scalar &borderValue)
 {
-       int cnn = src.channels();
-       switch( src.depth() )
+       Mat src = _src.getMat(), kernel = _kernel.getMat();
+       if( !( src.depth() == CV_8U || src.depth() == CV_32F ) || ( iterations > 1 ) || 
+               !( borderType == cv::BORDER_REPLICATE || (borderType == cv::BORDER_CONSTANT && borderValue == morphologyDefaultBorderValue()) ) 
+               || !( op == MORPH_DILATE || op == MORPH_ERODE) )
        {
-       case CV_8U:
+               return false;
+       }
+       if( borderType == cv::BORDER_CONSTANT )
+       {
+               int x, y;
+               for( y = 0; y < kernel.rows; y++ )
                {
-                       switch( cnn ) 
+                       if( kernel.at<uchar>(y, anchor.x) != 0 )
                        {
-                       case 1:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C1( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C1R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C1R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_8u_C1R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 3:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C3( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C3R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C3R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_8u_C3R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 4:
+                               continue;
+                       }
+                       for( x = 0; x < kernel.cols; x++ )
+                       {
+                               if( kernel.at<uchar>(y,x) != 0 )
                                {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp8u *data = (Ipp8u *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp8u *temp = ippiMalloc_8u_C4( src.cols, src.rows, &step );
-                                               ippiCopy_8u_C4R( (Ipp8u *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_8u_C4R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_8u_C4R( data, step,  (Ipp8u *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
+                                       return false;
                                }
                        }
-                       break;
                }
-       case CV_32F:
+               for( x = 0; y < kernel.cols; x++ )
                {
-                       switch( cnn )
+                       if( kernel.at<uchar>(anchor.y, x) != 0 )
                        {
-                       case 1:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C1( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C1R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C1R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_32f_C1R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 3:
-                               {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C3( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C3R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C3R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_32f_C3R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
-                               }
-                       case 4:
+                               continue;
+                       }
+                       for( y = 0; y < kernel.rows; y++ )
+                       {
+                               if( kernel.at<uchar>(y,x) != 0 )
                                {
-                                       IppiSize roiSize = {src.cols, src.rows};
-                                       Ipp32f *data = (Ipp32f *)src.data;
-                                       int step = src.step;
-                                       if( src.data == dst.data )
-                                       {
-                                               Ipp32f *temp = ippiMalloc_32f_C4( src.cols, src.rows, &step );
-                                               ippiCopy_32f_C4R( (Ipp32f *)src.data, src.step, temp, step, roiSize );
-                                               data = temp;
-                                       }
-                                       IppiMorphState* ppState;
-                                       IppiSize kernelSize = {kernel.cols, kernel.rows};
-                                       IppiPoint point = {anchor.x, anchor.y};
-                                       ippiMorphologyInitAlloc_32f_C4R( roiSize.width, (Ipp8u *)kernel.data, kernelSize, point, &ppState );
-                                       ippiErodeBorderReplicate_32f_C4R( data, step,  (Ipp32f *)dst.data, dst.step, roiSize, ippBorderRepl, ppState );
-                                       ippiMorphologyFree(ppState);
-                                       if( src.data == dst.data )
-                                       {
-                                               ippiFree(data);
-                                       }
-                                       return true;
+                                       return false;
                                }
                        }
-                       break;
                }
-       }
-       return false;
-}
 
-static bool IPPMorphOp(int op, InputArray _src, OutputArray _dst,
-                     InputArray _kernel,
-                     Point anchor, int iterations,
-                     int borderType)
-{
-       Mat src = _src.getMat(), kernel = _kernel.getMat();
-       if( !(src.depth() == CV_8U || src.depth() == CV_32F) || (iterations > 1) || 
-               (borderType != cv::BORDER_REPLICATE) || !( op == MORPH_DILATE || op == MORPH_ERODE) )
-       {
-               return false;
        }
        Size ksize = kernel.data ? kernel.size() : Size(3,3);
-    Point normanchor = normalizeAnchor(anchor, ksize);
+       Point normanchor = normalizeAnchor(anchor, ksize);
 
-    CV_Assert( normanchor.inside(Rect(0, 0, ksize.width, ksize.height)) );
+       CV_Assert( normanchor.inside(Rect(0, 0, ksize.width, ksize.height)) );
 
-    _dst.create( src.size(), src.type() );
-    Mat dst = _dst.getMat();
+       _dst.create( src.size(), src.type() );
+       Mat dst = _dst.getMat();
 
-    if( iterations == 0 || kernel.rows*kernel.cols == 1 )
-    {
-        src.copyTo(dst);
-        return true;
-    }
+       if( iterations == 0 || kernel.rows*kernel.cols == 1 )
+       {
+               src.copyTo(dst);
+               return true;
+       }
 
-    if( !kernel.data )
-    {
-        kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2));
-        normanchor = Point(iterations, iterations);
-        iterations = 1;
-    }
-    else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols )
-    {
-        normanchor = Point(normanchor.x*iterations, normanchor.y*iterations);
-        kernel = getStructuringElement(MORPH_RECT,
-                                       Size(ksize.width + (iterations-1)*(ksize.width-1),
-                                            ksize.height + (iterations-1)*(ksize.height-1)),
-                                       normanchor);
-        iterations = 1;
-    }
-       switch( op )
+       if( !kernel.data )
        {
-       case MORPH_DILATE:
-               {
-                       return IPPDilateReplicate( src, dst, kernel, normanchor );
-               }
-       case MORPH_ERODE:
-               {
-                       return IPPErodeReplicate( src, dst, kernel, normanchor );
-               }
+               kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2));
+               normanchor = Point(iterations, iterations);
+               iterations = 1;
        }
-       return false;
+       else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols )
+       {
+               normanchor = Point(normanchor.x*iterations, normanchor.y*iterations);
+               kernel = getStructuringElement(MORPH_RECT,
+                       Size(ksize.width + (iterations-1)*(ksize.width-1),
+                       ksize.height + (iterations-1)*(ksize.height-1)),
+                       normanchor);
+               iterations = 1;
+       }
+
+       return IPPMorphReplicate( op, src, dst, kernel, normanchor );
 }
 #endif
 
@@ -1521,7 +1293,7 @@ static void morphOp( int op, InputArray _src, OutputArray _dst,
 {
 
 #if defined (HAVE_IPP) && (IPP_VERSION_MAJOR >= 7)
-       if (IPPMorphOp(op, _src, _dst, _kernel, anchor, iterations, borderType))
+       if( IPPMorphOp(op, _src, _dst, _kernel, anchor, iterations, borderType, borderValue) )
        {
                return;
        }