Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

vimt_gaussian_pyramid_builder_2d.txx

Go to the documentation of this file.
00001 // This is mul/vimt/vimt_gaussian_pyramid_builder_2d.txx
00002 #ifndef vimt_gaussian_pyramid_builder_2d_txx_
00003 #define vimt_gaussian_pyramid_builder_2d_txx_
00004 //:
00005 // \file
00006 // \brief Class to build gaussian pyramids of vimt_image_2d_of<T>
00007 // \author Tim Cootes
00008 
00009 #include "vimt_gaussian_pyramid_builder_2d.h"
00010 
00011 #include <vcl_cstdlib.h>
00012 #include <vcl_string.h>
00013 
00014 #include <vcl_cassert.h>
00015 #include <vnl/vnl_math.h> // for sqrt2
00016 #include <vil/algo/vil_gauss_reduce.h>
00017 #include <vimt/vimt_image_pyramid.h>
00018 #include <vimt/vimt_crop.h>
00019 
00020 //=======================================================================
00021 
00022 template<class T>
00023 vimt_gaussian_pyramid_builder_2d<T>::vimt_gaussian_pyramid_builder_2d()
00024 : max_levels_(99),filter_width_(5)
00025 {
00026   set_min_size(5, 5);
00027 }
00028 
00029 //=======================================================================
00030 
00031 template<class T>
00032 vimt_gaussian_pyramid_builder_2d<T>::~vimt_gaussian_pyramid_builder_2d()
00033 {
00034 }
00035 
00036 //=======================================================================
00037 //: Define maximum number of levels to build
00038 //  Limits levels built in subsequent calls to build()
00039 template<class T>
00040 void vimt_gaussian_pyramid_builder_2d<T>::set_max_levels(int max_l)
00041 {
00042   if (max_l<1)
00043   {
00044     vcl_cerr<<"vimt_gaussian_pyramid_builder_2d<T>::setMaxLevels() ";
00045     vcl_cerr<<"Must be >=1\n";
00046     vcl_abort();
00047   }
00048   max_levels_ = max_l;
00049 }
00050 
00051 //: Get the current maximum number levels allowed
00052 template<class T>
00053 int vimt_gaussian_pyramid_builder_2d<T>::max_levels() const
00054 {
00055   return max_levels_;
00056 }
00057 
00058 //=======================================================================
00059 //: Create new (empty) pyramid on heap
00060 //  Caller responsible for its deletion
00061 template<class T>
00062 vimt_image_pyramid* vimt_gaussian_pyramid_builder_2d<T>::new_image_pyramid() const
00063 {
00064   return new vimt_image_pyramid;
00065 }
00066 
00067 //=======================================================================
00068 //: Scale step between levels
00069 template<class T>
00070 double vimt_gaussian_pyramid_builder_2d<T>::scale_step() const
00071 {
00072   return 2.0;
00073 }
00074 
00075 //: Set current filter width (must be 3 or 5 at present)
00076 template<class T>
00077 void vimt_gaussian_pyramid_builder_2d<T>::set_filter_width(unsigned w)
00078 {
00079   assert(w==3 || w==5);
00080   filter_width_ = w;
00081 }
00082 
00083 //: Smooth and subsample src_im to produce dest_im
00084 //  Applies filter in x and y, then samples every other pixel.
00085 template<class T>
00086 void vimt_gaussian_pyramid_builder_2d<T>::gauss_reduce(const vimt_image_2d_of<T>& src_im,
00087                                                        vimt_image_2d_of<T>& dest_im) const
00088 {
00089   switch (filter_width_)
00090   {
00091     case (3):
00092       vil_gauss_reduce_121(src_im.image(),dest_im.image());
00093       break;
00094     case (5):
00095       vil_gauss_reduce(src_im.image(),dest_im.image(),work_im_.image());
00096       break;
00097     default:
00098       vcl_cerr<<"vimt_gaussian_pyramid_builder_2d<T>::gauss_reduce() "
00099               <<"cannot cope with filter width of "<<filter_width_<<'\n';
00100       vcl_abort();
00101   }
00102 
00103   // Sort out world to image transformation for destination image
00104   vimt_transform_2d scaling;
00105   scaling.set_zoom_only(0.5,0,0);
00106   dest_im.set_world2im(scaling * src_im.world2im());
00107 }
00108 
00109 //=======================================================================
00110 //: Deletes all data in im_pyr
00111 template<class T>
00112 void vimt_gaussian_pyramid_builder_2d<T>::empty_pyr(vimt_image_pyramid& im_pyr) const
00113 {
00114   for (int i=0; i<im_pyr.n_levels();++i)
00115     delete im_pyr.data()[i];
00116 }
00117 
00118 //=======================================================================
00119 //: Checks pyramid has at least n levels
00120 template<class T>
00121 void vimt_gaussian_pyramid_builder_2d<T>::check_pyr(vimt_image_pyramid& im_pyr,  int n_levels) const
00122 {
00123   const int got_levels = im_pyr.n_levels();
00124   if (got_levels >= n_levels && im_pyr(0).is_class(work_im_.is_a()))
00125   {
00126     if (im_pyr.n_levels()==n_levels) return;
00127     else
00128     {
00129       for (int i=n_levels;i<got_levels;++i)
00130         delete im_pyr.data()[i];
00131     }
00132     im_pyr.data().resize(n_levels);
00133     return;
00134   }
00135 
00136   im_pyr.resize(n_levels,vimt_image_2d_of<T>());
00137 }
00138 
00139 //=======================================================================
00140 //: Build pyramid
00141 template<class T>
00142 void vimt_gaussian_pyramid_builder_2d<T>::build(vimt_image_pyramid& image_pyr,
00143                                                 const vimt_image& im) const
00144 {
00145   //  Require image vimt_image_2d_of<T>
00146   assert(im.is_class(work_im_.is_a()));
00147 
00148   const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00149 
00150   int ni = base_image.image().ni();
00151   int nj = base_image.image().nj();
00152 
00153   // Compute number of levels to pyramid so that top is no less
00154   // than minXSize_ x minYSize_
00155   int s = 1;
00156   int max_levels = 1;
00157   while ((ni/(2*s)>=int(minXSize_)) && (nj/(2*s)>=int(minYSize_)))
00158   {
00159     max_levels++;
00160     s*=2;
00161   }
00162 
00163   if (max_levels>max_levels_)
00164     max_levels=max_levels_;
00165 
00166   // Set up image pyramid
00167   check_pyr(image_pyr,max_levels);
00168 
00169   vimt_image_2d_of<T>& im0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(0));
00170 
00171   // Shallow copy of part of base_image
00172   im0 = vimt_crop(base_image,0,ni,0,nj);
00173 
00174   int i;
00175   for (i=1;i<max_levels;i++)
00176   {
00177     vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(i));
00178     vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00179 
00180     gauss_reduce(im_i1,im_i0);
00181   }
00182 
00183   // Estimate width of pixels in base image
00184   vgl_point_2d<double>  c0(0.5*(ni-1),0.5*(nj-1));
00185   vgl_point_2d<double>  c1 = c0 + vgl_vector_2d<double> (1,1);
00186   vimt_transform_2d im2world = base_image.world2im().inverse();
00187   vgl_vector_2d<double>  dw = im2world(c1) - im2world(c0);
00188 
00189   double base_pixel_width = dw.length()/vnl_math::sqrt2;
00190   double scale_step = 2.0;
00191 
00192   image_pyr.set_widths(base_pixel_width,scale_step);
00193 }
00194 
00195 //=======================================================================
00196 //: Extend pyramid
00197 // The first layer of the pyramid must already be set.
00198 template<class T>
00199 void vimt_gaussian_pyramid_builder_2d<T>::extend(vimt_image_pyramid& image_pyr) const
00200 {
00201   //  Require image vimt_image_2d_of<T>
00202   assert(image_pyr(0).is_class(work_im_.is_a()));
00203 
00204   assert(image_pyr.scale_step() == scale_step());
00205 
00206   vimt_image_2d_of<T>& im_base = static_cast<vimt_image_2d_of<T>&>( image_pyr(0));
00207   int ni = im_base.image().ni();
00208   int nj = im_base.image().nj();
00209 
00210   // Compute number of levels to pyramid so that top is no less
00211   // than 5 x 5
00212   double s = 1;
00213   int max_levels = 1;
00214   while ((ni/(scale_step()*s)>=minXSize_) && (nj/(scale_step()*s)>=minYSize_))
00215   {
00216     max_levels++;
00217     s*=scale_step();
00218   }
00219 
00220   if (max_levels>max_levels_)
00221     max_levels=max_levels_;
00222 
00223   // Set up image pyramid
00224   int oldsize = image_pyr.n_levels();
00225   if (oldsize<max_levels) // only extend, if it isn't already tall enough
00226   {
00227     image_pyr.data().resize(max_levels);
00228 
00229     int i;
00230     for (i=oldsize;i<max_levels;++i)
00231       image_pyr.data()[i] = new vimt_image_2d_of<T>;
00232 
00233     for (i=oldsize;i<max_levels;i++)
00234     {
00235       vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(i));
00236       vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00237 
00238       gauss_reduce(im_i1,im_i0);
00239     }
00240   }
00241 }
00242 
00243 
00244 //=======================================================================
00245 
00246 #if 0
00247 template<class T>
00248 vcl_string vimt_gaussian_pyramid_builder_2d<T>::is_a() const
00249 {
00250   return vcl_string("vimt_gaussian_pyramid_builder_2d<T>");
00251 }
00252 #endif
00253 
00254 //=======================================================================
00255 
00256 template<class T>
00257 bool vimt_gaussian_pyramid_builder_2d<T>::is_class(vcl_string const& s) const
00258 {
00259   return s==vimt_gaussian_pyramid_builder_2d<T>::is_a() || vimt_image_pyramid_builder::is_class(s);
00260 }
00261 
00262 //=======================================================================
00263 
00264 template<class T>
00265 short vimt_gaussian_pyramid_builder_2d<T>::version_no() const
00266 {
00267   return 2;
00268 }
00269 
00270 //=======================================================================
00271 
00272 template<class T>
00273 vimt_image_pyramid_builder* vimt_gaussian_pyramid_builder_2d<T>::clone() const
00274 {
00275   return new vimt_gaussian_pyramid_builder_2d<T>(*this);
00276 }
00277 
00278 //=======================================================================
00279 
00280 template<class T>
00281 void vimt_gaussian_pyramid_builder_2d<T>::print_summary(vcl_ostream&) const
00282 {
00283 }
00284 
00285 //=======================================================================
00286 
00287 template<class T>
00288 void vimt_gaussian_pyramid_builder_2d<T>::b_write(vsl_b_ostream& bfs) const
00289 {
00290   vsl_b_write(bfs,version_no());
00291   vsl_b_write(bfs,max_levels_);
00292   vsl_b_write(bfs,filter_width_);
00293 }
00294 
00295 //=======================================================================
00296 
00297 template<class T>
00298 void vimt_gaussian_pyramid_builder_2d<T>::b_read(vsl_b_istream& bfs)
00299 {
00300   if (!bfs) return;
00301 
00302   short version;
00303   vsl_b_read(bfs,version);
00304   switch (version)
00305   {
00306   // version number starts at 2 to follow on from the old mil stuff
00307   case (2):
00308     vsl_b_read(bfs,max_levels_);
00309     vsl_b_read(bfs,filter_width_);
00310     break;
00311   default:
00312     vcl_cerr << "I/O ERROR: vimt_gaussian_pyramid_builder_2d<T>::b_read(vsl_b_istream&)\n";
00313     vcl_cerr << "           Unknown version number "<< version << "\n";
00314     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00315     return;
00316   }
00317 }
00318 
00319 #define VIMT_GAUSSIAN_PYRAMID_BUILDER_2D_INSTANTIATE(T) \
00320 VCL_DEFINE_SPECIALIZATION vcl_string vimt_gaussian_pyramid_builder_2d<T >::is_a() const \
00321 {  return vcl_string("vimt_gaussian_pyramid_builder_2d<" #T ">"); }\
00322 template class vimt_gaussian_pyramid_builder_2d<T >
00323 
00324 #endif // vimt_gaussian_pyramid_builder_2d_txx_

Generated on Thu Jan 10 14:43:58 2008 for contrib/mul/vimt by  doxygen 1.4.4