Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

bilateral_filter.h

Go to the documentation of this file.
00001 
00055 #ifndef __BILATERAL_FILTER__
00056 #define __BILATERAL_FILTER__
00057 
00058 #include <cmath>
00059 
00060 #include "array.h"
00061 #include "math_tools.h"
00062 
00063 
00064 
00065 /*
00066 
00067 ##########################
00068 # class Bilateral_filter #
00069 ##########################
00070 
00071 */
00072 
00073 
00081 template <typename Space_weight_function,
00082           typename Data_weight_function>
00083 class Bilateral_filter{
00084 
00085 public:
00086 
00087   typedef unsigned int size_type;
00088   
00089   Bilateral_filter(Space_weight_function& space_w,
00090                    Data_weight_function&  data_w);
00091   
00092 
00093   template<typename Data_array>
00094   void pixel_filter(const size_type x,
00095                     const size_type y,
00096                     const Data_array& data,
00097                     typename Data_array::value_type* const result);
00098 
00100   template<typename Data_array>
00101   void array_filter(const Data_array& data,
00102                     Data_array* const result);
00103 
00104 
00105 private:
00106 
00107   Space_weight_function& space_weight;
00108   Data_weight_function&  data_weight;
00109 };
00110 
00111 
00112 
00113 
00114 /*
00115 
00116 ###############################
00117 # class Gaussian_space_weight #
00118 ###############################
00119 
00120 */
00121 
00124 class Gaussian_space_weight{
00125 
00126 public:
00127 
00128   typedef unsigned int size_type;
00129   typedef float        real_type;
00130 
00131   inline Gaussian_space_weight(const real_type sig);
00132 
00133   inline size_type far() const;
00134   
00135   inline bool is_far(const int dx,const int dy) const;
00136 
00137   inline void set_reference_data(const size_type x,
00138                                  const size_type y);
00139   
00140   inline real_type operator()(const size_type x,
00141                               const size_type y) const;
00142   
00143 private:
00144   const real_type sigma;
00145   const int       far_threshold;
00146 
00147   size_type x_ref,y_ref;
00148 
00150   Array_2D<real_type> weight;
00151 };
00152 
00153 
00154 
00155 
00156 
00157 
00158 
00159 
00160 
00161 
00162 
00163 /*
00164   ###########################################################
00165   ###########################################################
00166   ###########################################################
00167   ##############                               ##############
00168   ##############  I M P L E M E N T A T I O N  ##############
00169   ##############                               ##############
00170   ###########################################################
00171   ###########################################################
00172   ###########################################################
00173 */
00174 
00175 
00176 
00177 
00178 
00179 
00180 
00181 
00182 /*
00183 
00184 ##########################
00185 # class Bilateral_filter #
00186 ##########################
00187 
00188 */
00189 
00190 
00191 template <typename Space_weight_function,
00192           typename Data_weight_function>
00193 Bilateral_filter<Space_weight_function,Data_weight_function>::
00194 Bilateral_filter(Space_weight_function& space_w,
00195                  Data_weight_function&  data_w):
00196   space_weight(space_w),
00197   data_weight(data_w){
00198 }
00199 
00200 
00201 template <typename Space_weight_function,
00202           typename Data_weight_function>
00203 template <typename Data_array>
00204 void
00205 Bilateral_filter<Space_weight_function,Data_weight_function>::
00206 pixel_filter(const size_type x,
00207              const size_type y,
00208              const Data_array& data,
00209              typename Data_array::value_type* const result){
00210 
00211   using namespace Math_tools;
00212   
00213   const size_type width  = data.x_size();
00214   const size_type height = data.y_size();
00215 
00216   const int far = static_cast<int>(space_weight.far());
00217 
00218   const size_type x_begin = clamp<int>(0,width-1,static_cast<int>(x)-far);
00219   const size_type x_end   = clamp<int>(0,width-1,static_cast<int>(x)+far);
00220   
00221   const size_type y_begin = clamp<int>(0,height-1,static_cast<int>(y)-far);
00222   const size_type y_end   = clamp<int>(0,height-1,static_cast<int>(y)+far);
00223 
00224   real_type weight_sum = 0;
00225   *result *= 0;
00226 
00227   space_weight.set_reference_data(x,y);
00228   data_weight.set_reference_data(x,y);
00229   
00230   for(size_type i=x_begin;i<=x_end;i++){
00231     for(size_type j=y_begin;j<=y_end;j++){
00232 
00233       real_type weight = space_weight(i,j) * data_weight(i,j);
00234       *result += weight * data(i,j);
00235       weight_sum += weight;
00236     }
00237   }
00238 
00239   if (weight_sum == 0){
00240     *result = data(x,y);
00241   }
00242   else{
00243     *result /= weight_sum;
00244   }
00245 }
00246 
00247 
00248 
00249 template <typename Space_weight_function,
00250           typename Data_weight_function>
00251 template <typename Data_array>
00252 void
00253 Bilateral_filter<Space_weight_function,Data_weight_function>::
00254 array_filter(const Data_array& data,
00255              Data_array* const result){
00256 
00257   const size_type width  = data.x_size();
00258   const size_type height = data.y_size();
00259 
00260   Data_array target(width,height);
00261 
00262   for(size_type x=0;x<width;x++){
00263     for(size_type y=0;y<height;y++){
00264       pixel_filter(x,y,data,&target);
00265     }
00266   }
00267 
00268   result->swap(target);
00269 }
00270 
00271 
00272 
00273 /*
00274 
00275 ###############################
00276 # class Gaussian_space_weight #
00277 ###############################
00278 
00279 */
00280 
00281 
00282 
00283 Gaussian_space_weight::Gaussian_space_weight(const real_type sig):
00284   sigma(sig),
00285   far_threshold(2*static_cast<int>(sig+1)){
00286 
00287 
00288   weight.resize(2*far_threshold+1,2*far_threshold+1);
00289 
00290   for(int dx=0;dx<=far_threshold;dx++){
00291     for(int dy=0;dy<=far_threshold;dy++){
00292       const real_type x = static_cast<real_type>(dx) / sigma;
00293       const real_type y = static_cast<real_type>(dy) / sigma;
00294       const real_type g = std::exp(-0.5*(x*x+y*y));
00295 
00296       weight(far_threshold-dx,far_threshold-dy) = g;
00297       weight(far_threshold+dx,far_threshold-dy) = g;
00298       weight(far_threshold+dx,far_threshold+dy) = g;
00299       weight(far_threshold-dx,far_threshold+dy) = g;
00300     }
00301   }
00302 }
00303 
00304 
00305 
00306 inline Gaussian_space_weight::size_type
00307 Gaussian_space_weight::far() const{
00308   
00309   return far_threshold;
00310 }
00311 
00312 
00313 
00314 bool Gaussian_space_weight::is_far(const int dx,const int dy) const{
00315 
00316   return
00317     (dx>far_threshold) || (dx<-far_threshold) ||
00318     (dy>far_threshold) || (dy<-far_threshold);
00319 }
00320 
00321 
00322 void Gaussian_space_weight::set_reference_data(const size_type x,
00323                                                const size_type y){
00324     x_ref = x;
00325     y_ref = y;
00326   }
00327 
00328 
00329 Gaussian_space_weight::real_type
00330 Gaussian_space_weight::operator()(const size_type x,
00331                                   const size_type y) const{
00332 
00333   const int dx = static_cast<int>(x_ref) - static_cast<int>(x);
00334   const int dy = static_cast<int>(y_ref) - static_cast<int>(y);
00335   
00336   return (is_far(dx,dy) ? 0 : weight(far_threshold+dx,far_threshold+dy));
00337 }
00338 
00339 #endif

Generated on Fri Aug 20 15:03:52 2004 by doxygen1.2.18