1 // This is core/vil/algo/vil_dog_pyramid.h
2 #ifndef vil_dog_pyramid_h_
3 #define vil_dog_pyramid_h_
4 //:
5 // \file
6 // \brief Compute a pyramid of difference of gaussian images
7 // \author Tim Cootes
8 
9 #include <vector>
10 #include <vil/algo/vil_gauss_filter.h>
11 #include <vil/vil_resample_bilin.h>
12 #include <vil/vil_math.h>
13 #ifdef _MSC_VER
14 #  include <vcl_msvc_warnings.h>
15 #endif
16 
17 //: Compute a pyramid of difference of gaussian images
18 //  Computes each layer of a pyramid by smoothing
19 //  then computing the difference from the original image.
20 //  The smoothed is then subsampled using a reduction factor of 1.5
21 //  (ie each level is 2/3 the size of the level below) and
22 //  used to produced the next level.
23 //
24 //  min_size defines the smallest dimension (restricting the number
25 //  of levels that will be constructed)
26 //
27 //  This is useful for finding locally interesting points and their
28 //  associated scales - see "Object Recognition from Scale Invariant Features"
29 //  D.Lowe, ICCV1999, pp.1150-1157.
30 //  \relatesalso vil_image_view
31 template<class T>
vil_dog_pyramid(const vil_image_view<T> & src_image,std::vector<vil_image_view<T>> & smooth_pyramid,std::vector<vil_image_view<T>> & dog_pyramid,unsigned min_size)32 void vil_dog_pyramid(const vil_image_view<T>& src_image,
33                      std::vector<vil_image_view<T> >& smooth_pyramid,
34                      std::vector<vil_image_view<T> >& dog_pyramid,
35                      unsigned min_size)
36 {
37   // Compute number of levels to build
38   unsigned n = std::min(src_image.ni(),src_image.nj());
39   unsigned nL = 0;
40   while (n>min_size) { nL++; n=(2*n)/3; }
41 
42   smooth_pyramid.resize(nL);
43   dog_pyramid.resize(nL);
44 
45   vil_image_view<T> sub_sampled_image;
46 
47   if (nL==0) return;
48 
49   vil_gauss_filter_5tap_params smooth_params(1.41421);
50 
51   // First level
52 
53   vil_gauss_filter_5tap(src_image,smooth_pyramid[0],smooth_params,
54                         dog_pyramid[0]);  // Workspace
55   vil_math_image_difference(src_image,smooth_pyramid[0],dog_pyramid[0]);
56 
57   unsigned n_planes = src_image.nplanes();
58 
59   double scaling = 1.5;
60 
61   // Subsequent levels
62   for (unsigned i=1;i<nL;++i)
63   {
64     // Subsample by a factor of 2/3
65     // Note - this could be implemented more efficiently
66     //        since bilinear is sampling at pixel positions
67     //        and on edges.
68     unsigned ni = smooth_pyramid[i-1].ni();
69     unsigned nj = smooth_pyramid[i-1].nj();
70     ni = 2*ni/3;
71     nj = 2*nj/3;
72     sub_sampled_image.set_size(ni,nj,n_planes);
73     vil_resample_bilin(smooth_pyramid[i-1],sub_sampled_image,
74                        0.0,0.0, scaling,0.0,  0.0,scaling, ni,nj);
75 
76     vil_gauss_filter_5tap(sub_sampled_image,smooth_pyramid[i],
77                           smooth_params,
78                           dog_pyramid[i]);  // Workspace
79     vil_math_image_difference(sub_sampled_image,smooth_pyramid[i],
80                               dog_pyramid[i]);
81   }
82 }
83 
84 
85 #endif
86