diff --git a/modules/calib3d/src/stereosgbm.cpp b/modules/calib3d/src/stereosgbm.cpp index 5dfb31cc9c..8caab41b82 100644 --- a/modules/calib3d/src/stereosgbm.cpp +++ b/modules/calib3d/src/stereosgbm.cpp @@ -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 + void filterSpecklesImpl(cv::Mat& img, int newVal, int maxSpeckleSize, int maxDiff, cv::Mat& _buf) { - short* ds = img.ptr(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(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(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(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(img, newVal, maxSpeckleSize, maxDiff, _buf); + else + filterSpecklesImpl(img, newVal, maxSpeckleSize, maxDiff, _buf); +} + void cv::validateDisparity( InputOutputArray _disp, InputArray _cost, int minDisparity, int numberOfDisparities, int disp12MaxDiff ) {