added 8u type support to filterSpeckles function
authorVladislav Vinogradov <vlad.vinogradov@itseez.com>
Wed, 6 Feb 2013 06:30:26 +0000 (10:30 +0400)
committerVladislav Vinogradov <vlad.vinogradov@itseez.com>
Wed, 6 Feb 2013 10:14:45 +0000 (14:14 +0400)
modules/calib3d/src/stereosgbm.cpp

index 5dfb31c..8caab41 100644 (file)
@@ -857,107 +857,122 @@ Rect getValidDisparityROI( Rect roi1, Rect roi2,
 
 }
 
-void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize,
-                         double _maxDiff, InputOutputArray __buf )
+namespace
 {
-    Mat img = _img.getMat();
-    Mat temp, &_buf = __buf.needed() ? __buf.getMatRef() : temp;
-    CV_Assert( img.type() == CV_16SC1 );
-
-    int newVal = cvRound(_newval);
-    int maxDiff = cvRound(_maxDiff);
-    int width = img.cols, height = img.rows, npixels = width*height;
-    size_t bufSize = npixels*(int)(sizeof(Point2s) + sizeof(int) + sizeof(uchar));
-    if( !_buf.isContinuous() || !_buf.data || _buf.cols*_buf.rows*_buf.elemSize() < bufSize )
-        _buf.create(1, (int)bufSize, CV_8U);
-
-    uchar* buf = _buf.data;
-    int i, j, dstep = (int)(img.step/sizeof(short));
-    int* labels = (int*)buf;
-    buf += npixels*sizeof(labels[0]);
-    Point2s* wbuf = (Point2s*)buf;
-    buf += npixels*sizeof(wbuf[0]);
-    uchar* rtype = (uchar*)buf;
-    int curlabel = 0;
-
-    // clear out label assignments
-    memset(labels, 0, npixels*sizeof(labels[0]));
-
-    for( i = 0; i < height; i++ )
+    template <typename T>
+    void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDiff, cv::Mat& _buf)
     {
-        short* ds = img.ptr<short>(i);
-        int* ls = labels + width*i;
-
-        for( j = 0; j < width; j++ )
+        using namespace cv;
+
+        int width = img.cols, height = img.rows, npixels = width*height;
+        size_t bufSize = npixels*(int)(sizeof(Point2s) + sizeof(int) + sizeof(uchar));
+        if( !_buf.isContinuous() || !_buf.data || _buf.cols*_buf.rows*_buf.elemSize() < bufSize )
+            _buf.create(1, (int)bufSize, CV_8U);
+
+        uchar* buf = _buf.data;
+        int i, j, dstep = (int)(img.step/sizeof(T));
+        int* labels = (int*)buf;
+        buf += npixels*sizeof(labels[0]);
+        Point2s* wbuf = (Point2s*)buf;
+        buf += npixels*sizeof(wbuf[0]);
+        uchar* rtype = (uchar*)buf;
+        int curlabel = 0;
+
+        // clear out label assignments
+        memset(labels, 0, npixels*sizeof(labels[0]));
+
+        for( i = 0; i < height; i++ )
         {
-            if( ds[j] != newVal )   // not a bad disparity
+            T* ds = img.ptr<T>(i);
+            int* ls = labels + width*i;
+
+            for( j = 0; j < width; j++ )
             {
-                if( ls[j] )     // has a label, check for bad label
-                {
-                    if( rtype[ls[j]] ) // small region, zero out disparity
-                        ds[j] = (short)newVal;
-                }
-                // no label, assign and propagate
-                else
+                if( ds[j] != newVal )   // not a bad disparity
                 {
-                    Point2s* ws = wbuf; // initialize wavefront
-                    Point2s p((short)j, (short)i);  // current pixel
-                    curlabel++; // next label
-                    int count = 0;  // current region size
-                    ls[j] = curlabel;
-
-                    // wavefront propagation
-                    while( ws >= wbuf ) // wavefront not empty
+                    if( ls[j] )     // has a label, check for bad label
                     {
-                        count++;
-                        // put neighbors onto wavefront
-                        short* dpp = &img.at<short>(p.y, p.x);
-                        short dp = *dpp;
-                        int* lpp = labels + width*p.y + p.x;
-
-                        if( p.x < width-1 && !lpp[+1] && dpp[+1] != newVal && std::abs(dp - dpp[+1]) <= maxDiff )
+                        if( rtype[ls[j]] ) // small region, zero out disparity
+                            ds[j] = (T)newVal;
+                    }
+                    // no label, assign and propagate
+                    else
+                    {
+                        Point2s* ws = wbuf; // initialize wavefront
+                        Point2s p((short)j, (short)i);  // current pixel
+                        curlabel++; // next label
+                        int count = 0;  // current region size
+                        ls[j] = curlabel;
+
+                        // wavefront propagation
+                        while( ws >= wbuf ) // wavefront not empty
                         {
-                            lpp[+1] = curlabel;
-                            *ws++ = Point2s(p.x+1, p.y);
-                        }
+                            count++;
+                            // put neighbors onto wavefront
+                            T* dpp = &img.at<T>(p.y, p.x);
+                            T dp = *dpp;
+                            int* lpp = labels + width*p.y + p.x;
 
-                        if( p.x > 0 && !lpp[-1] && dpp[-1] != newVal && std::abs(dp - dpp[-1]) <= maxDiff )
-                        {
-                            lpp[-1] = curlabel;
-                            *ws++ = Point2s(p.x-1, p.y);
-                        }
+                            if( p.x < width-1 && !lpp[+1] && dpp[+1] != newVal && std::abs(dp - dpp[+1]) <= maxDiff )
+                            {
+                                lpp[+1] = curlabel;
+                                *ws++ = Point2s(p.x+1, p.y);
+                            }
 
-                        if( p.y < height-1 && !lpp[+width] && dpp[+dstep] != newVal && std::abs(dp - dpp[+dstep]) <= maxDiff )
-                        {
-                            lpp[+width] = curlabel;
-                            *ws++ = Point2s(p.x, p.y+1);
+                            if( p.x > 0 && !lpp[-1] && dpp[-1] != newVal && std::abs(dp - dpp[-1]) <= maxDiff )
+                            {
+                                lpp[-1] = curlabel;
+                                *ws++ = Point2s(p.x-1, p.y);
+                            }
+
+                            if( p.y < height-1 && !lpp[+width] && dpp[+dstep] != newVal && std::abs(dp - dpp[+dstep]) <= maxDiff )
+                            {
+                                lpp[+width] = curlabel;
+                                *ws++ = Point2s(p.x, p.y+1);
+                            }
+
+                            if( p.y > 0 && !lpp[-width] && dpp[-dstep] != newVal && std::abs(dp - dpp[-dstep]) <= maxDiff )
+                            {
+                                lpp[-width] = curlabel;
+                                *ws++ = Point2s(p.x, p.y-1);
+                            }
+
+                            // pop most recent and propagate
+                            // NB: could try least recent, maybe better convergence
+                            p = *--ws;
                         }
 
-                        if( p.y > 0 && !lpp[-width] && dpp[-dstep] != newVal && std::abs(dp - dpp[-dstep]) <= maxDiff )
+                        // assign label type
+                        if( count <= maxSpeckleSize )   // speckle region
                         {
-                            lpp[-width] = curlabel;
-                            *ws++ = Point2s(p.x, p.y-1);
+                            rtype[ls[j]] = 1;   // small region label
+                            ds[j] = (T)newVal;
                         }
-
-                        // pop most recent and propagate
-                        // NB: could try least recent, maybe better convergence
-                        p = *--ws;
-                    }
-
-                    // assign label type
-                    if( count <= maxSpeckleSize )   // speckle region
-                    {
-                        rtype[ls[j]] = 1;   // small region label
-                        ds[j] = (short)newVal;
+                        else
+                            rtype[ls[j]] = 0;   // large region label
                     }
-                    else
-                        rtype[ls[j]] = 0;   // large region label
                 }
             }
         }
     }
 }
 
+void cv::filterSpeckles( InputOutputArray _img, double _newval, int maxSpeckleSize,
+                         double _maxDiff, InputOutputArray __buf )
+{
+    Mat img = _img.getMat();
+    Mat temp, &_buf = __buf.needed() ? __buf.getMatRef() : temp;
+    CV_Assert( img.type() == CV_8UC1 || img.type() == CV_16SC1 );
+
+    int newVal = cvRound(_newval);
+    int maxDiff = cvRound(_maxDiff);
+
+    if (img.type() == CV_8UC1)
+        filterSpecklesImpl<uchar>(img, newVal, maxSpeckleSize, maxDiff, _buf);
+    else
+        filterSpecklesImpl<short>(img, newVal, maxSpeckleSize, maxDiff, _buf);
+}
+
 void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity,
                             int numberOfDisparities, int disp12MaxDiff )
 {