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