00001
00002 #ifndef vimt_dog_pyramid_builder_2d_txx_
00003 #define vimt_dog_pyramid_builder_2d_txx_
00004
00005
00006
00007
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>
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
00039
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
00052 template<class T>
00053 int vimt_dog_pyramid_builder_2d<T>::max_levels() const
00054 {
00055 return max_levels_;
00056 }
00057
00058
00059
00060
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
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
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
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
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
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
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
00135
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
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());
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
00170 vimt_transform_2d scaling_trans;
00171 scaling_trans.set_zoom_only(2.0/3.0,0,0);
00172
00173
00174 vil_image_view<T> sub_sampled_image;
00175
00176
00177
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
00185
00186
00187
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());
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
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
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
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);
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>& ,
00302 vimt_image_2d_of<T>& ) 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_