@ -2624,285 +2624,6 @@ void cv::bilateralFilter( InputArray _src, OutputArray _dst, int d,
" Bilateral filtering is only implemented for 8u and 32f images " ) ;
" 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
CV_IMPL void