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

vimt_gaussian_pyramid_builder_2d_general.txx

Go to the documentation of this file.
00001 // This is mul/vimt/vimt_gaussian_pyramid_builder_2d_general.txx
00002 #ifndef vimt_gaussian_pyramid_builder_2d_general_txx_
00003 #define vimt_gaussian_pyramid_builder_2d_general_txx_
00004 //:
00005 // \file
00006 // \brief Build gaussian image pyramids at any scale separation
00007 // \author Ian Scott
00008 
00009 #include "vimt_gaussian_pyramid_builder_2d_general.h"
00010 #include <vcl_cmath.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_string.h>
00013 #include <vcl_iostream.h>
00014 #include <vil/algo/vil_gauss_reduce.h>
00015 #include <vimt/vimt_image_pyramid.h>
00016 #include <vimt/vimt_crop.h>
00017 
00018 //=======================================================================
00019 
00020 template <class T>
00021 vimt_gaussian_pyramid_builder_2d_general<T>::vimt_gaussian_pyramid_builder_2d_general():
00022   scale_params_(2.0)
00023 {}
00024 
00025 //: Construct with given scale_step
00026 template <class T>
00027 vimt_gaussian_pyramid_builder_2d_general<T>::vimt_gaussian_pyramid_builder_2d_general(double scale_step):
00028   scale_params_(scale_step)
00029 {}
00030 
00031 //=======================================================================
00032 
00033 template <class T>
00034 vimt_gaussian_pyramid_builder_2d_general<T>::~vimt_gaussian_pyramid_builder_2d_general()
00035 {}
00036 
00037 //: Set the Scale step
00038 template <class T>
00039 void vimt_gaussian_pyramid_builder_2d_general<T>::set_scale_step(double scaleStep)
00040 {
00041   scale_params_ = vil_gauss_reduce_params(scaleStep);
00042 }
00043 
00044 //=======================================================================
00045 
00046 template <class T>
00047 void vimt_gaussian_pyramid_builder_2d_general<T>::build(
00048                   vimt_image_pyramid& im_pyr,
00049                   const vimt_image& im) const
00050 {
00051   assert(im.is_class(vimt_image_2d_of<T>().is_a()));
00052 
00053   const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00054 
00055   int ni = base_image.image().ni();
00056   int nj = base_image.image().nj();
00057 
00058   // Compute number of levels to pyramid so that top is no less
00059   // than minXSize_ x minYSize_
00060   double s = scale_step();
00061   int maxlevels = 1;
00062   while (((unsigned int)(ni/s+0.5)>=this->min_x_size()) &&
00063          ((unsigned int)(nj/s+0.5)>=this->min_y_size()))
00064   {
00065     maxlevels++;
00066     s *= scale_step();
00067   }
00068 
00069   if (maxlevels > this->max_levels())
00070     maxlevels=this->max_levels();
00071 
00072   worka_.set_size(ni,nj);
00073   workb_.set_size(ni,nj);
00074 
00075   // Set up image pyramid
00076   this->check_pyr(im_pyr,maxlevels);
00077 
00078   vimt_image_2d_of<T>& im0 = static_cast<vimt_image_2d_of<T>&>(im_pyr(0));
00079 
00080   // Shallow copy of part of base_image
00081   im0 = vimt_crop(base_image,0,ni,0,nj);
00082 
00083   s = scale_step();
00084   for (int i=1;i<maxlevels;i++)
00085   {
00086     vimt_image_2d_of<T>& dest = static_cast<vimt_image_2d_of<T>&>(im_pyr(i));
00087     const vimt_image_2d_of<T>& src = static_cast<const vimt_image_2d_of<T>&>(im_pyr(i-1));
00088 
00089     s*=scale_step();
00090     vil_gauss_reduce_general(src.image(), dest.image(), worka_, workb_, scale_params_);
00091 
00092     // Sort out world to image transformation for destination image
00093     vimt_transform_2d scaling;
00094 
00095     // use n-1 because we are trying to align inter-pixel spaces, so that the
00096     // centre pixel is most accurately registered despite buildup of rounding errors.
00097     const double init_x = 0.5 * (src.image().ni() - 1 - (dest.image().ni()-1)*scale_params_.scale_step());
00098     const double init_y = 0.5 * (src.image().nj() - 1 - (dest.image().nj()-1)*scale_params_.scale_step());
00099 
00100     scaling.set_zoom_only(1/scale_params_.scale_step(),-init_x,-init_y);
00101     dest.set_world2im(scaling * src.world2im());
00102   }
00103 
00104   // Estimate width of pixels in base image
00105   vgl_point_2d<double>  c0(0.5*(ni-1),0.5*(nj-1));
00106   vgl_point_2d<double>  c1 = c0 + vgl_vector_2d<double> (1,1);
00107   vimt_transform_2d im2world = base_image.world2im().inverse();
00108   vgl_vector_2d<double>  dw = im2world(c1) - im2world(c0);
00109 
00110   double base_pixel_width = vcl_sqrt(0.5*(dw.x()*dw.x() + dw.y()*dw.y()));
00111 
00112   im_pyr.set_widths(base_pixel_width,scale_step());
00113 }
00114 
00115 
00116 //=======================================================================
00117 //: Extend pyramid
00118 // The first layer of the pyramid must already be set.
00119 template<class T>
00120 void vimt_gaussian_pyramid_builder_2d_general<T>::extend(vimt_image_pyramid& image_pyr) const
00121 {
00122   //  Require image vil_image_view<T>
00123   assert(image_pyr(0).is_class(vimt_image_2d_of<T>().is_a()));
00124 
00125   assert(image_pyr.scale_step() == scale_step());
00126 
00127   const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(image_pyr(0));
00128 
00129 
00130   const int ni = base_image.image().ni();
00131   const int nj = base_image.image().nj();
00132 
00133   // Compute number of levels to pyramid so that top is no less
00134   // than 5 x 5
00135   double s = scale_step();
00136   int maxlevels = 1;
00137   while (((unsigned int)(ni/s+0.5) >= this->min_x_size()) &&
00138          ((unsigned int)(nj/s+0.5) >= this->min_y_size()))
00139   {
00140      maxlevels++;
00141      s*=scale_step();
00142   }
00143 
00144   if (maxlevels > this->max_levels())
00145     maxlevels=this->max_levels();
00146 
00147   worka_.set_size(ni,nj);
00148   workb_.set_size(ni,nj);
00149 
00150   // Set up image pyramid
00151   int oldsize = image_pyr.n_levels();
00152   if (oldsize<maxlevels) // only extend, if it isn't already tall enough
00153   {
00154     image_pyr.data().resize(maxlevels);
00155 
00156     s = vcl_pow(scale_step(), oldsize);
00157     for (int i=oldsize;i<maxlevels;i++)
00158     {
00159       image_pyr.data()[i] = new vimt_image_2d_of<T>;
00160       vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i));
00161       vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00162       im_i0.image().set_size((unsigned)(ni/s+0.5),(unsigned)(nj/s+0.5),
00163         im_i1.image().nplanes());
00164 
00165       s*=scale_step();
00166       vil_gauss_reduce_general(im_i1.image(), im_i0.image(), worka_, workb_, scale_params_);
00167     }
00168   }
00169 }
00170 
00171 
00172 //=======================================================================
00173 #if 0
00174 template <class T>
00175 vcl_string vimt_gaussian_pyramid_builder_2d_general<T>::is_a() const
00176 {
00177   return vcl_string("vimt_gaussian_pyramid_builder_2d_general<T>");
00178 }
00179 #endif // 0
00180 //=======================================================================
00181 
00182 template <class T>
00183 bool vimt_gaussian_pyramid_builder_2d_general<T>::is_class(vcl_string const& s) const
00184 {
00185   return s==vimt_gaussian_pyramid_builder_2d_general<T>::is_a() ||
00186          vimt_gaussian_pyramid_builder_2d<T>::is_class(s);
00187 }
00188 
00189 //=======================================================================
00190 
00191 template <class T>
00192 short vimt_gaussian_pyramid_builder_2d_general<T>::version_no() const
00193 {
00194   return 1;
00195 }
00196 
00197 //=======================================================================
00198 
00199 template <class T>
00200 vimt_image_pyramid_builder* vimt_gaussian_pyramid_builder_2d_general<T>::clone() const
00201 {
00202   return new vimt_gaussian_pyramid_builder_2d_general(*this);
00203 }
00204 
00205 //=======================================================================
00206 
00207 template <class T>
00208 void vimt_gaussian_pyramid_builder_2d_general<T>::print_summary(vcl_ostream& os) const
00209 {
00210   vimt_gaussian_pyramid_builder_2d<T>::print_summary(os);
00211 }
00212 
00213 //=======================================================================
00214 
00215 template <class T>
00216 void vimt_gaussian_pyramid_builder_2d_general<T>::b_write(vsl_b_ostream& bfs) const
00217 {
00218   vsl_b_write(bfs,version_no());
00219   vimt_gaussian_pyramid_builder_2d<T>::b_write(bfs);
00220   vsl_b_write(bfs,scale_step());
00221 }
00222 
00223 //=======================================================================
00224 
00225 template <class T>
00226 void vimt_gaussian_pyramid_builder_2d_general<T>::b_read(vsl_b_istream& bfs)
00227 {
00228   if (!bfs) return;
00229 
00230   short version;
00231   vsl_b_read(bfs,version);
00232   double scale;
00233 
00234   switch (version)
00235   {
00236    case 1:
00237     vimt_gaussian_pyramid_builder_2d<T>::b_read(bfs);
00238 
00239     vsl_b_read(bfs,scale);
00240     set_scale_step(scale);
00241     break;
00242    default:
00243     vcl_cerr << "I/O ERROR: vimt_gaussian_pyramid_builder_2d_general<T>::b_read(vsl_b_istream&)\n"
00244              << "           Unknown version number "<< version << '\n';
00245     bfs.is().clear(vcl_ios::badbit); // Set an unrecoverable IO error on stream
00246     return;
00247   }
00248 }
00249 
00250 #define VIMT_GAUSSIAN_PYRAMID_BUILDER_2D_GENERAL_INSTANTIATE(T) \
00251 VCL_DEFINE_SPECIALIZATION vcl_string vimt_gaussian_pyramid_builder_2d_general<T >::is_a() const \
00252 {  return vcl_string("vimt_gaussian_pyramid_builder_2d_general<" #T ">"); }\
00253 template class vimt_gaussian_pyramid_builder_2d_general<T >
00254 
00255 
00256 #endif // vimt_gaussian_pyramid_builder_2d_general_txx_

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