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 <vgl/vgl_point_2d.h>
00018 #include <vgl/vgl_vector_2d.h>
00019 #include <vil/algo/vil_gauss_filter.h>
00020 #include <vil/vil_resample_bilin.h>
00021 #include <vil/vil_math.h>
00022
00023
00024
00025 template<class T>
00026 vimt_dog_pyramid_builder_2d<T>::vimt_dog_pyramid_builder_2d()
00027 : max_levels_(99)
00028 {
00029 set_min_size(5, 5);
00030 }
00031
00032
00033
00034 template<class T>
00035 vimt_dog_pyramid_builder_2d<T>::~vimt_dog_pyramid_builder_2d()
00036 {
00037 }
00038
00039
00040
00041
00042 template<class T>
00043 void vimt_dog_pyramid_builder_2d<T>::set_max_levels(int max_l)
00044 {
00045 if (max_l<1)
00046 {
00047 vcl_cerr<<"vimt_dog_pyramid_builder_2d<T>::set_max_levels() argument must be >=1\n";
00048 vcl_abort();
00049 }
00050 max_levels_ = max_l;
00051 }
00052
00053
00054 template<class T>
00055 int vimt_dog_pyramid_builder_2d<T>::max_levels() const
00056 {
00057 return max_levels_;
00058 }
00059
00060
00061
00062
00063 template<class T>
00064 vimt_image_pyramid* vimt_dog_pyramid_builder_2d<T>::new_image_pyramid() const
00065 {
00066 return new vimt_image_pyramid;
00067 }
00068
00069
00070
00071 template<class T>
00072 double vimt_dog_pyramid_builder_2d<T>::scale_step() const
00073 {
00074 return 1.5;
00075 }
00076
00077
00078
00079
00080 template<class T>
00081 void vimt_dog_pyramid_builder_2d<T>::empty_pyr(vimt_image_pyramid& im_pyr) const
00082 {
00083 for (int i=0; i<im_pyr.n_levels();++i)
00084 delete im_pyr.data()[i];
00085 }
00086
00087
00088
00089 template<class T>
00090 void vimt_dog_pyramid_builder_2d<T>::check_pyr(vimt_image_pyramid& im_pyr, int n_levels) const
00091 {
00092 const int got_levels = im_pyr.n_levels();
00093 if (got_levels >= n_levels && im_pyr(0).is_class(work_im_.is_a()))
00094 {
00095 if (im_pyr.n_levels()==n_levels) return;
00096 else
00097 {
00098 for (int i=n_levels;i<got_levels;++i)
00099 delete im_pyr.data()[i];
00100 }
00101 im_pyr.data().resize(n_levels);
00102 return;
00103 }
00104
00105 im_pyr.data().resize(n_levels);
00106 empty_pyr(im_pyr);
00107
00108 for (int i=0;i<n_levels;++i)
00109 im_pyr.data()[i] = new vimt_image_2d_of<T>;
00110 }
00111
00112
00113 template<class T>
00114 void vimt_dog_pyramid_builder_2d<T>::build(vimt_image_pyramid& dog_pyr,
00115 const vimt_image& im) const
00116 {
00117 vimt_image_pyramid smooth_pyr;
00118 build_dog(dog_pyr,smooth_pyr,im);
00119 }
00120
00121
00122
00123 template<class T>
00124 void vimt_dog_pyramid_builder_2d<T>::build_dog(vimt_image_pyramid& dog_pyr,
00125 vimt_image_pyramid& smooth_pyr,
00126 const vimt_image& im, bool abs_diff) const
00127 {
00128
00129 assert(im.is_class(work_im_.is_a()));
00130
00131 const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00132
00133 unsigned ni = base_image.image().ni();
00134 unsigned nj = base_image.image().nj();
00135
00136
00137
00138 int max_levels = 1;
00139 while (ni>min_x_size_ && nj>min_y_size_)
00140 {
00141 max_levels++;
00142 ni = 2*ni/3;
00143 nj = 2*nj/3;
00144 }
00145
00146 if (max_levels>max_levels_)
00147 max_levels=max_levels_;
00148
00149
00150 check_pyr(dog_pyr,max_levels);
00151 check_pyr(smooth_pyr,max_levels);
00152
00153 vimt_image_2d_of<T>& smooth0 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(0));
00154 vimt_image_2d_of<T>& dog0 = static_cast<vimt_image_2d_of<T>&>( dog_pyr(0));
00155
00156 vil_gauss_filter_5tap_params smooth_params(0.75);
00157
00158 vil_gauss_filter_5tap(base_image.image(),smooth0.image(),smooth_params,
00159 dog0.image());
00160
00161 if (abs_diff)
00162 vil_math_image_abs_difference(base_image.image(),smooth0.image(),dog0.image());
00163 else
00164 vil_math_image_difference(base_image.image(),smooth0.image(),dog0.image());
00165
00166 smooth0.set_world2im(base_image.world2im());
00167 dog0.set_world2im(base_image.world2im());
00168
00169 unsigned n_planes = base_image.image().nplanes();
00170
00171
00172 vimt_transform_2d scaling_trans;
00173 scaling_trans.set_zoom_only(2.0/3.0,0,0);
00174
00175
00176 vil_image_view<T> sub_sampled_image;
00177
00178
00179
00180 for (int i=1;i<max_levels;++i)
00181 {
00182 vimt_image_2d_of<T>& smooth0 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(i-1));
00183 vimt_image_2d_of<T>& smooth1 = static_cast<vimt_image_2d_of<T>&>( smooth_pyr(i));
00184 vimt_image_2d_of<T>& dog1 = static_cast<vimt_image_2d_of<T>&>( dog_pyr(i));
00185
00186
00187
00188
00189
00190 unsigned ni = smooth0.image().ni();
00191 unsigned nj = smooth0.image().nj();
00192 ni = 2*ni/3;
00193 nj = 2*nj/3;
00194 sub_sampled_image.set_size(ni,nj,n_planes);
00195
00196 vil_resample_bilin(smooth0.image(),sub_sampled_image,
00197 0.0,0.0, 1.5,0.0, 0.0,1.5, ni,nj);
00198
00199 vil_gauss_filter_5tap(sub_sampled_image,smooth1.image(),
00200 smooth_params,
00201 dog1.image());
00202 if (abs_diff)
00203 vil_math_image_abs_difference(sub_sampled_image,smooth1.image(),
00204 dog1.image());
00205 else
00206 vil_math_image_difference(sub_sampled_image,smooth1.image(),
00207 dog1.image());
00208
00209 smooth1.set_world2im(scaling_trans*smooth0.world2im());
00210 dog1.set_world2im(smooth1.world2im());
00211 }
00212
00213
00214 vgl_point_2d<double> c0(0.5*(ni-1),0.5*(nj-1));
00215 vgl_point_2d<double> c1 = c0 + vgl_vector_2d<double> (1,1);
00216 vimt_transform_2d im2world = base_image.world2im().inverse();
00217 vgl_vector_2d<double> dw = im2world(c1) - im2world(c0);
00218
00219 double base_pixel_width = dw.length()/vnl_math::sqrt2;
00220 double scale_step = 1.5;
00221
00222 dog_pyr.set_widths(base_pixel_width,scale_step);
00223 smooth_pyr.set_widths(base_pixel_width,scale_step);
00224 }
00225
00226
00227
00228 template<class T>
00229 void vimt_dog_pyramid_builder_2d<T>::extend(vimt_image_pyramid& ) const
00230 {
00231 vcl_cerr << "vimt_dog_pyramid_builder_2d<T>::extend(vimt_image_pyramid&) NYI\n";
00232 }
00233
00234
00235
00236
00237 template<class T>
00238 bool vimt_dog_pyramid_builder_2d<T>::is_class(vcl_string const& s) const
00239 {
00240 return s==vimt_dog_pyramid_builder_2d<T>::is_a() || vimt_image_pyramid_builder::is_class(s);
00241 }
00242
00243
00244
00245 template<class T>
00246 short vimt_dog_pyramid_builder_2d<T>::version_no() const
00247 {
00248 return 1;
00249 }
00250
00251
00252
00253 template<class T>
00254 vimt_image_pyramid_builder* vimt_dog_pyramid_builder_2d<T>::clone() const
00255 {
00256 return new vimt_dog_pyramid_builder_2d<T>(*this);
00257 }
00258
00259
00260
00261 template<class T>
00262 void vimt_dog_pyramid_builder_2d<T>::print_summary(vcl_ostream&) const
00263 {
00264 }
00265
00266
00267
00268 template<class T>
00269 void vimt_dog_pyramid_builder_2d<T>::b_write(vsl_b_ostream& bfs) const
00270 {
00271 vsl_b_write(bfs,version_no());
00272 vsl_b_write(bfs,max_levels_);
00273 vsl_b_write(bfs,min_x_size_);
00274 vsl_b_write(bfs,min_y_size_);
00275 }
00276
00277
00278
00279 template<class T>
00280 void vimt_dog_pyramid_builder_2d<T>::b_read(vsl_b_istream& bfs)
00281 {
00282 if (!bfs) return;
00283
00284 short version;
00285 vsl_b_read(bfs,version);
00286 switch (version)
00287 {
00288
00289 case (1):
00290 vsl_b_read(bfs,max_levels_);
00291 vsl_b_read(bfs,min_x_size_);
00292 vsl_b_read(bfs,min_y_size_);
00293 break;
00294 default:
00295 vcl_cerr << "I/O ERROR: vimt_dog_pyramid_builder_2d<T>::b_read(vsl_b_istream&)\n"
00296 << " Unknown version number "<< version << '\n';
00297 bfs.is().clear(vcl_ios::badbit);
00298 return;
00299 }
00300 }
00301
00302 template<class T>
00303 void vimt_dog_pyramid_builder_2d<T>::gauss_reduce(const vimt_image_2d_of<T>& ,
00304 vimt_image_2d_of<T>& ) const
00305 {
00306 vcl_cerr << "ERROR: vimt_dog_pyramid_builder_2d<T>::gauss_reduce() not yet implemented\n";
00307 }
00308
00309 #define VIMT_DOG_PYRAMID_BUILDER_2D_INSTANTIATE(T) \
00310 VCL_DEFINE_SPECIALIZATION vcl_string vimt_dog_pyramid_builder_2d<T >::is_a() const \
00311 { return vcl_string("vimt_dog_pyramid_builder_2d<" #T ">"); }\
00312 template class vimt_dog_pyramid_builder_2d<T >
00313
00314 #endif // vimt_dog_pyramid_builder_2d_txx_