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

vimt_dog_pyramid_builder_2d.txx

Go to the documentation of this file.
00001 // This is mul/vimt/vimt_dog_pyramid_builder_2d.txx
00002 #ifndef vimt_dog_pyramid_builder_2d_txx_
00003 #define vimt_dog_pyramid_builder_2d_txx_
00004 //:
00005 // \file
00006 // \brief Build difference of gaussian pyramids of vimt_image_2d_of<T>
00007 // \author Tim Cootes
00008 
00009 #include "vimt_dog_pyramid_builder_2d.h"
00010 #include "vimt_image_pyramid.h"
00011 
00012 #include <vcl_cstdlib.h>
00013 #include <vcl_string.h>
00014 
00015 #include <vcl_cassert.h>
00016 #include <vnl/vnl_math.h> // for sqrt2
00017 #include <vil/algo/vil_gauss_filter.h>
00018 #include <vil/vil_resample_bilin.h>
00019 #include <vil/vil_math.h>
00020 
00021 //=======================================================================
00022 
00023 template<class T>
00024 vimt_dog_pyramid_builder_2d<T>::vimt_dog_pyramid_builder_2d()
00025 : max_levels_(99)
00026 {
00027   set_min_size(5, 5);
00028 }
00029 
00030 //=======================================================================
00031 
00032 template<class T>
00033 vimt_dog_pyramid_builder_2d<T>::~vimt_dog_pyramid_builder_2d()
00034 {
00035 }
00036 
00037 //=======================================================================
00038 //: Define maximum number of levels to build
00039 //  Limits levels built in subsequent calls to build()
00040 template<class T>
00041 void vimt_dog_pyramid_builder_2d<T>::set_max_levels(int max_l)
00042 {
00043   if (max_l<1)
00044   {
00045     vcl_cerr<<"vimt_dog_pyramid_builder_2d<T>::set_max_levels() argument 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_dog_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_dog_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_dog_pyramid_builder_2d<T>::scale_step() const
00071 {
00072   return 1.5;
00073 }
00074 
00075 
00076 //=======================================================================
00077 //: Deletes all data in im_pyr
00078 template<class T>
00079 void vimt_dog_pyramid_builder_2d<T>::empty_pyr(vimt_image_pyramid& im_pyr) const
00080 {
00081   for (int i=0; i<im_pyr.n_levels();++i)
00082     delete im_pyr.data()[i];
00083 }
00084 
00085 //=======================================================================
00086 //: Checks pyramid has at least n levels
00087 template<class T>
00088 void vimt_dog_pyramid_builder_2d<T>::check_pyr(vimt_image_pyramid& im_pyr,  int n_levels) const
00089 {
00090   const int got_levels = im_pyr.n_levels();
00091   if (got_levels >= n_levels && im_pyr(0).is_class(work_im_.is_a()))
00092   {
00093     if (im_pyr.n_levels()==n_levels) return;
00094     else
00095     {
00096       for (int i=n_levels;i<got_levels;++i)
00097         delete im_pyr.data()[i];
00098     }
00099     im_pyr.data().resize(n_levels);
00100     return;
00101   }
00102 
00103   im_pyr.data().resize(n_levels);
00104   empty_pyr(im_pyr);
00105 
00106   for (int i=0;i<n_levels;++i)
00107     im_pyr.data()[i] = new vimt_image_2d_of<T>;
00108 }
00109 
00110 //: Build pyramid
00111 template<class T>
00112 void vimt_dog_pyramid_builder_2d<T>::build(vimt_image_pyramid& dog_pyr,
00113                                            const vimt_image& im) const
00114 {
00115   vimt_image_pyramid smooth_pyr;
00116   build_dog(dog_pyr,smooth_pyr,im);
00117 }
00118 
00119 //=======================================================================
00120 //: Build pyramid
00121 template<class T>
00122 void vimt_dog_pyramid_builder_2d<T>::build_dog(vimt_image_pyramid& dog_pyr,
00123                                                vimt_image_pyramid& smooth_pyr,
00124                                                const vimt_image& im, bool abs_diff) const
00125 {
00126   //  Require image vimt_image_2d_of<T>
00127   assert(im.is_class(work_im_.is_a()));
00128 
00129   const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00130 
00131   unsigned ni = base_image.image().ni();
00132   unsigned nj = base_image.image().nj();
00133 
00134   // Compute number of levels to pyramid so that top is no less
00135   // than min_x_size_ x min_y_size_
00136   int max_levels = 1;
00137   while (ni>min_x_size_ && nj>min_y_size_)
00138   {
00139     max_levels++;
00140     ni = 2*ni/3;
00141     nj = 2*nj/3;
00142   }
00143 
00144   if (max_levels>max_levels_)
00145     max_levels=max_levels_;
00146 
00147   // Set up image pyramid
00148   check_pyr(dog_pyr,max_levels);
00149   check_pyr(smooth_pyr,max_levels);
00150 
00151   vimt_image_2d_of<T>& smooth0 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(0));
00152   vimt_image_2d_of<T>& dog0 = static_cast<vimt_image_2d_of<T>&>( dog_pyr(0));
00153 
00154   vil_gauss_filter_5tap_params smooth_params(0.75);
00155 
00156   vil_gauss_filter_5tap(base_image.image(),smooth0.image(),smooth_params,
00157                         dog0.image());  // Workspace
00158 
00159   if (abs_diff)
00160     vil_math_image_abs_difference(base_image.image(),smooth0.image(),dog0.image());
00161   else
00162     vil_math_image_difference(base_image.image(),smooth0.image(),dog0.image());
00163 
00164   smooth0.set_world2im(base_image.world2im());
00165   dog0.set_world2im(base_image.world2im());
00166 
00167   unsigned n_planes = base_image.image().nplanes();
00168 
00169   // Sort out world to image transformation for destination image
00170   vimt_transform_2d scaling_trans;
00171   scaling_trans.set_zoom_only(2.0/3.0,0,0);
00172 
00173   // Workspace
00174   vil_image_view<T> sub_sampled_image;
00175 
00176 
00177   // Subsequent levels
00178   for (int i=1;i<max_levels;++i)
00179   {
00180     vimt_image_2d_of<T>& smooth0 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(i-1));
00181     vimt_image_2d_of<T>& smooth1 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(i));
00182     vimt_image_2d_of<T>& dog1 = static_cast<vimt_image_2d_of<T>&>( dog_pyr(i));
00183 
00184     // Subsample by a factor of 2/3
00185     // Note - this could be implemented more efficiently
00186     //        since bilinear is sampling at pixel positions
00187     //        and on edges.
00188     unsigned ni = smooth0.image().ni();
00189     unsigned nj = smooth0.image().nj();
00190     ni = 2*ni/3;
00191     nj = 2*nj/3;
00192     sub_sampled_image.set_size(ni,nj,n_planes);
00193 
00194     vil_resample_bilin(smooth0.image(),sub_sampled_image,
00195                        0.0,0.0, 1.5,0.0,  0.0,1.5, ni,nj);
00196 
00197     vil_gauss_filter_5tap(sub_sampled_image,smooth1.image(),
00198                           smooth_params,
00199                           dog1.image());  // Workspace
00200     if (abs_diff)
00201       vil_math_image_abs_difference(sub_sampled_image,smooth1.image(),
00202                                     dog1.image());
00203     else
00204       vil_math_image_difference(sub_sampled_image,smooth1.image(),
00205                                 dog1.image());
00206 
00207     smooth1.set_world2im(scaling_trans*smooth0.world2im());
00208     dog1.set_world2im(smooth1.world2im());
00209   }
00210 
00211   // Estimate width of pixels in base image
00212   vgl_point_2d<double>  c0(0.5*(ni-1),0.5*(nj-1));
00213   vgl_point_2d<double>  c1 = c0 + vgl_vector_2d<double> (1,1);
00214   vimt_transform_2d im2world = base_image.world2im().inverse();
00215   vgl_vector_2d<double>  dw = im2world(c1) - im2world(c0);
00216 
00217   double base_pixel_width = dw.length()/vnl_math::sqrt2;
00218   double scale_step = 1.5;
00219 
00220   dog_pyr.set_widths(base_pixel_width,scale_step);
00221   smooth_pyr.set_widths(base_pixel_width,scale_step);
00222 }
00223 
00224 //=======================================================================
00225 //: Extend pyramid (not implemented)
00226 template<class T>
00227 void vimt_dog_pyramid_builder_2d<T>::extend(vimt_image_pyramid& ) const
00228 {
00229   vcl_cerr << "vimt_dog_pyramid_builder_2d<T>::extend(vimt_image_pyramid&) NYI\n";
00230 }
00231 
00232 
00233 //=======================================================================
00234 
00235 template<class T>
00236 bool vimt_dog_pyramid_builder_2d<T>::is_class(vcl_string const& s) const
00237 {
00238   return s==vimt_dog_pyramid_builder_2d<T>::is_a() || vimt_image_pyramid_builder::is_class(s);
00239 }
00240 
00241 //=======================================================================
00242 
00243 template<class T>
00244 short vimt_dog_pyramid_builder_2d<T>::version_no() const
00245 {
00246   return 1;
00247 }
00248 
00249 //=======================================================================
00250 
00251 template<class T>
00252 vimt_image_pyramid_builder* vimt_dog_pyramid_builder_2d<T>::clone() const
00253 {
00254   return new vimt_dog_pyramid_builder_2d<T>(*this);
00255 }
00256 
00257 //=======================================================================
00258 
00259 template<class T>
00260 void vimt_dog_pyramid_builder_2d<T>::print_summary(vcl_ostream&) const
00261 {
00262 }
00263 
00264 //=======================================================================
00265 
00266 template<class T>
00267 void vimt_dog_pyramid_builder_2d<T>::b_write(vsl_b_ostream& bfs) const
00268 {
00269   vsl_b_write(bfs,version_no());
00270   vsl_b_write(bfs,max_levels_);
00271   vsl_b_write(bfs,min_x_size_);
00272   vsl_b_write(bfs,min_y_size_);
00273 }
00274 
00275 //=======================================================================
00276 
00277 template<class T>
00278 void vimt_dog_pyramid_builder_2d<T>::b_read(vsl_b_istream& bfs)
00279 {
00280   if (!bfs) return;
00281 
00282   short version;
00283   vsl_b_read(bfs,version);
00284   switch (version)
00285   {
00286    // version number starts at 2 to follow on from the old mil stuff
00287    case (1):
00288     vsl_b_read(bfs,max_levels_);
00289     vsl_b_read(bfs,min_x_size_);
00290     vsl_b_read(bfs,min_y_size_);
00291     break;
00292    default:
00293     vcl_cerr << "I/O ERROR: vimt_dog_pyramid_builder_2d<T>::b_read(vsl_b_istream&)\n"
00294              << "           Unknown version number "<< version << '\n';
00295     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00296     return;
00297   }
00298 }
00299 
00300 template<class T>
00301 void vimt_dog_pyramid_builder_2d<T>::gauss_reduce(const vimt_image_2d_of<T>& /*src_im*/,
00302                                                   vimt_image_2d_of<T>& /*dest_im*/) const
00303 {
00304   vcl_cerr << "ERROR: vimt_dog_pyramid_builder_2d<T>::gauss_reduce() not yet implemented\n";
00305 }
00306 
00307 #define VIMT_DOG_PYRAMID_BUILDER_2D_INSTANTIATE(T) \
00308 VCL_DEFINE_SPECIALIZATION vcl_string vimt_dog_pyramid_builder_2d<T >::is_a() const \
00309 {  return vcl_string("vimt_dog_pyramid_builder_2d<" #T ">"); }\
00310 template class vimt_dog_pyramid_builder_2d<T >
00311 
00312 #endif // vimt_dog_pyramid_builder_2d_txx_

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