core/vil/algo/vil_dog_pyramid.h
Go to the documentation of this file.
00001 // This is core/vil/algo/vil_dog_pyramid.h
00002 #ifndef vil_dog_pyramid_h_
00003 #define vil_dog_pyramid_h_
00004 //:
00005 // \file
00006 // \brief Compute a pyramid of difference of gaussian images
00007 // \author Tim Cootes
00008 
00009 #include <vil/algo/vil_gauss_filter.h>
00010 #include <vil/vil_resample_bilin.h>
00011 #include <vil/vil_math.h>
00012 #include <vcl_vector.h>
00013 
00014 //: Compute a pyramid of difference of gaussian images
00015 //  Computes each layer of a pyramid by smoothing
00016 //  then computing the difference from the original image.
00017 //  The smoothed is then subsampled using a reduction factor of 1.5
00018 //  (ie each level is 2/3 the size of the level below) and
00019 //  used to produced the next level.
00020 //
00021 //  min_size defines the smallest dimension (restricting the number
00022 //  of levels that will be constructed)
00023 //
00024 //  This is useful for finding locally interesting points and their
00025 //  associated scales - see "Object Recognition from Scale Invariant Features"
00026 //  D.Lowe, ICCV1999, pp.1150-1157.
00027 //  \relatesalso vil_image_view
00028 template<class T>
00029 void vil_dog_pyramid(const vil_image_view<T>& src_image,
00030                      vcl_vector<vil_image_view<T> >& smooth_pyramid,
00031                      vcl_vector<vil_image_view<T> >& dog_pyramid,
00032                      unsigned min_size)
00033 {
00034   // Compute number of levels to build
00035   unsigned n = vcl_min(src_image.ni(),src_image.nj());
00036   unsigned nL = 0;
00037   while (n>min_size) { nL++; n=(2*n)/3; }
00038 
00039   smooth_pyramid.resize(nL);
00040   dog_pyramid.resize(nL);
00041 
00042   vil_image_view<T> sub_sampled_image;
00043 
00044   if (nL==0) return;
00045 
00046   vil_gauss_filter_5tap_params smooth_params(1.41421);
00047 
00048   // First level
00049 
00050   vil_gauss_filter_5tap(src_image,smooth_pyramid[0],smooth_params,
00051                         dog_pyramid[0]);  // Workspace
00052   vil_math_image_difference(src_image,smooth_pyramid[0],dog_pyramid[0]);
00053 
00054   unsigned n_planes = src_image.nplanes();
00055 
00056   double scaling = 1.5;
00057 
00058   // Subsequent levels
00059   for (unsigned i=1;i<nL;++i)
00060   {
00061     // Subsample by a factor of 2/3
00062     // Note - this could be implemented more efficiently
00063     //        since bilinear is sampling at pixel positions
00064     //        and on edges.
00065     unsigned ni = smooth_pyramid[i-1].ni();
00066     unsigned nj = smooth_pyramid[i-1].nj();
00067     ni = 2*ni/3;
00068     nj = 2*nj/3;
00069     sub_sampled_image.set_size(ni,nj,n_planes);
00070     vil_resample_bilin(smooth_pyramid[i-1],sub_sampled_image,
00071                        0.0,0.0, scaling,0.0,  0.0,scaling, ni,nj);
00072 
00073     vil_gauss_filter_5tap(sub_sampled_image,smooth_pyramid[i],
00074                           smooth_params,
00075                           dog_pyramid[i]);  // Workspace
00076     vil_math_image_difference(sub_sampled_image,smooth_pyramid[i],
00077                               dog_pyramid[i]);
00078   }
00079 }
00080 
00081 
00082 #endif