"Bilateral filtering is only implemented for 8u and 32f images" );
}
-
-/****************************************************************************************\
- Adaptive Bilateral Filtering
-\****************************************************************************************/
-
-namespace cv
-{
-#ifndef ABF_CALCVAR
-#define ABF_CALCVAR 1
-#endif
-
-#ifndef ABF_FIXED_WEIGHT
-#define ABF_FIXED_WEIGHT 0
-#endif
-
-#ifndef ABF_GAUSSIAN
-#define ABF_GAUSSIAN 1
-#endif
-
-class adaptiveBilateralFilter_8u_Invoker :
- public ParallelLoopBody
-{
-public:
- adaptiveBilateralFilter_8u_Invoker(Mat& _dest, const Mat& _temp, Size _ksize, double _sigma_space, double _maxSigmaColor, Point _anchor) :
- temp(&_temp), dest(&_dest), ksize(_ksize), sigma_space(_sigma_space), maxSigma_Color(_maxSigmaColor), anchor(_anchor)
- {
- if( sigma_space <= 0 )
- sigma_space = 1;
- CV_Assert((ksize.width & 1) && (ksize.height & 1));
- space_weight.resize(ksize.width * ksize.height);
- double sigma2 = sigma_space * sigma_space;
- int idx = 0;
- int w = ksize.width / 2;
- int h = ksize.height / 2;
- for(int y=-h; y<=h; y++)
- for(int x=-w; x<=w; x++)
- {
-#if ABF_GAUSSIAN
- space_weight[idx++] = (float)exp ( -0.5*(x * x + y * y)/sigma2);
-#else
- space_weight[idx++] = (float)(sigma2 / (sigma2 + x * x + y * y));
-#endif
- }
- }
- virtual void operator()(const Range& range) const
- {
- int cn = dest->channels();
- int anX = anchor.x;
-
- const uchar *tptr;
-
- for(int i = range.start;i < range.end; i++)
- {
- int startY = i;
- if(cn == 1)
- {
- float var;
- int currVal;
- int sumVal = 0;
- int sumValSqr = 0;
- int currValCenter;
- int currWRTCenter;
- float weight;
- float totalWeight = 0.;
- float tmpSum = 0.;
-
- for(int j = 0;j < dest->cols *cn; j+=cn)
- {
- sumVal = 0;
- sumValSqr= 0;
- totalWeight = 0.;
- tmpSum = 0.;
-
- // Top row: don't sum the very last element
- int startLMJ = 0;
- int endLMJ = ksize.width - 1;
- int howManyAll = (anX *2 +1)*(ksize.width );
-#if ABF_CALCVAR
- for(int x = startLMJ; x< endLMJ; x++)
- {
- tptr = temp->ptr(startY + x) +j;
- for(int y=-anX; y<=anX; y++)
- {
- currVal = tptr[cn*(y+anX)];
- sumVal += currVal;
- sumValSqr += (currVal *currVal);
- }
- }
- var = ( (sumValSqr * howManyAll)- sumVal * sumVal ) / ( (float)(howManyAll*howManyAll));
-
- if(var < 0.01)
- var = 0.01f;
- else if(var > (float)(maxSigma_Color*maxSigma_Color) )
- var = (float)(maxSigma_Color*maxSigma_Color) ;
-
-#else
- var = maxSigmaColor*maxSigmaColor;
-#endif
- startLMJ = 0;
- endLMJ = ksize.width;
- tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2);
- currValCenter =tptr[j+cn*anX];
- for(int x = startLMJ; x< endLMJ; x++)
- {
- tptr = temp->ptr(startY + x) +j;
- for(int y=-anX; y<=anX; y++)
- {
-#if ABF_FIXED_WEIGHT
- weight = 1.0;
-#else
- currVal = tptr[cn*(y+anX)];
- currWRTCenter = currVal - currValCenter;
-
-#if ABF_GAUSSIAN
- weight = exp ( -0.5f * currWRTCenter * currWRTCenter/var ) * space_weight[x*ksize.width+y+anX];
-#else
- weight = var / ( var + (currWRTCenter * currWRTCenter) ) * space_weight[x*ksize.width+y+anX];
-#endif
-
-#endif
- tmpSum += ((float)tptr[cn*(y+anX)] * weight);
- totalWeight += weight;
- }
- }
- tmpSum /= totalWeight;
-
- dest->at<uchar>(startY ,j)= static_cast<uchar>(tmpSum);
- }
- }
- else
- {
- assert(cn == 3);
- float var_b, var_g, var_r;
- int currVal_b, currVal_g, currVal_r;
- int sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
- int sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
- int currValCenter_b= 0, currValCenter_g= 0, currValCenter_r= 0;
- int currWRTCenter_b, currWRTCenter_g, currWRTCenter_r;
- float weight_b, weight_g, weight_r;
- float totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
- float tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
-
- for(int j = 0;j < dest->cols *cn; j+=cn)
- {
- sumVal_b= 0, sumVal_g= 0, sumVal_r= 0;
- sumValSqr_b= 0, sumValSqr_g= 0, sumValSqr_r= 0;
- totalWeight_b= 0., totalWeight_g= 0., totalWeight_r= 0.;
- tmpSum_b = 0., tmpSum_g= 0., tmpSum_r = 0.;
-
- // Top row: don't sum the very last element
- int startLMJ = 0;
- int endLMJ = ksize.width - 1;
- int howManyAll = (anX *2 +1)*(ksize.width);
-#if ABF_CALCVAR
- float max_var = (float)( maxSigma_Color*maxSigma_Color);
- for(int x = startLMJ; x< endLMJ; x++)
- {
- tptr = temp->ptr(startY + x) +j;
- for(int y=-anX; y<=anX; y++)
- {
- currVal_b = tptr[cn*(y+anX)], currVal_g = tptr[cn*(y+anX)+1], currVal_r =tptr[cn*(y+anX)+2];
- sumVal_b += currVal_b;
- sumVal_g += currVal_g;
- sumVal_r += currVal_r;
- sumValSqr_b += (currVal_b *currVal_b);
- sumValSqr_g += (currVal_g *currVal_g);
- sumValSqr_r += (currVal_r *currVal_r);
- }
- }
- var_b = ( (sumValSqr_b * howManyAll)- sumVal_b * sumVal_b ) / ( (float)(howManyAll*howManyAll));
- var_g = ( (sumValSqr_g * howManyAll)- sumVal_g * sumVal_g ) / ( (float)(howManyAll*howManyAll));
- var_r = ( (sumValSqr_r * howManyAll)- sumVal_r * sumVal_r ) / ( (float)(howManyAll*howManyAll));
-
- if(var_b < 0.01)
- var_b = 0.01f;
- else if(var_b > max_var )
- var_b = (float)(max_var) ;
-
- if(var_g < 0.01)
- var_g = 0.01f;
- else if(var_g > max_var )
- var_g = (float)(max_var) ;
-
- if(var_r < 0.01)
- var_r = 0.01f;
- else if(var_r > max_var )
- var_r = (float)(max_var) ;
-
-#else
- var_b = maxSigma_Color*maxSigma_Color; var_g = maxSigma_Color*maxSigma_Color; var_r = maxSigma_Color*maxSigma_Color;
-#endif
- startLMJ = 0;
- endLMJ = ksize.width;
- tptr = temp->ptr(startY + (startLMJ+ endLMJ)/2) + j;
- currValCenter_b =tptr[cn*anX], currValCenter_g =tptr[cn*anX+1], currValCenter_r =tptr[cn*anX+2];
- for(int x = startLMJ; x< endLMJ; x++)
- {
- tptr = temp->ptr(startY + x) +j;
- for(int y=-anX; y<=anX; y++)
- {
-#if ABF_FIXED_WEIGHT
- weight_b = 1.0;
- weight_g = 1.0;
- weight_r = 1.0;
-#else
- currVal_b = tptr[cn*(y+anX)];currVal_g=tptr[cn*(y+anX)+1];currVal_r=tptr[cn*(y+anX)+2];
- currWRTCenter_b = currVal_b - currValCenter_b;
- currWRTCenter_g = currVal_g - currValCenter_g;
- currWRTCenter_r = currVal_r - currValCenter_r;
-
- float cur_spw = space_weight[x*ksize.width+y+anX];
-
-#if ABF_GAUSSIAN
- weight_b = exp( -0.5f * currWRTCenter_b * currWRTCenter_b/ var_b ) * cur_spw;
- weight_g = exp( -0.5f * currWRTCenter_g * currWRTCenter_g/ var_g ) * cur_spw;
- weight_r = exp( -0.5f * currWRTCenter_r * currWRTCenter_r/ var_r ) * cur_spw;
-#else
- weight_b = var_b / ( var_b + (currWRTCenter_b * currWRTCenter_b) ) * cur_spw;
- weight_g = var_g / ( var_g + (currWRTCenter_g * currWRTCenter_g) ) * cur_spw;
- weight_r = var_r / ( var_r + (currWRTCenter_r * currWRTCenter_r) ) * cur_spw;
-#endif
-#endif
- tmpSum_b += ((float)tptr[cn*(y+anX)] * weight_b);
- tmpSum_g += ((float)tptr[cn*(y+anX)+1] * weight_g);
- tmpSum_r += ((float)tptr[cn*(y+anX)+2] * weight_r);
- totalWeight_b += weight_b, totalWeight_g += weight_g, totalWeight_r += weight_r;
- }
- }
- tmpSum_b /= totalWeight_b;
- tmpSum_g /= totalWeight_g;
- tmpSum_r /= totalWeight_r;
-
- dest->at<uchar>(startY,j )= static_cast<uchar>(tmpSum_b);
- dest->at<uchar>(startY,j+1)= static_cast<uchar>(tmpSum_g);
- dest->at<uchar>(startY,j+2)= static_cast<uchar>(tmpSum_r);
- }
- }
- }
- }
-private:
- const Mat *temp;
- Mat *dest;
- Size ksize;
- double sigma_space;
- double maxSigma_Color;
- Point anchor;
- std::vector<float> space_weight;
-};
-static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
-{
- Size size = src.size();
-
- CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) &&
- src.type() == dst.type() && src.size() == dst.size() &&
- src.data != dst.data );
- Mat temp;
- copyMakeBorder(src, temp, anchor.x, anchor.y, anchor.x, anchor.y, borderType);
-
- adaptiveBilateralFilter_8u_Invoker body(dst, temp, ksize, sigmaSpace, maxSigmaColor, anchor);
- parallel_for_(Range(0, size.height), body, dst.total()/(double)(1<<16));
-}
-}
-void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize,
- double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
-{
- Mat src = _src.getMat();
- _dst.create(src.size(), src.type());
- Mat dst = _dst.getMat();
-
- CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3);
-
- anchor = normalizeAnchor(anchor,ksize);
- if( src.depth() == CV_8U )
- adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, maxSigmaColor, anchor, borderType );
- else
- CV_Error( CV_StsUnsupportedFormat,
- "Adaptive Bilateral filtering is only implemented for 8u images" );
-}
-
//////////////////////////////////////////////////////////////////////////////////////////
CV_IMPL void