00001
00002 #ifndef vimt_gaussian_pyramid_builder_2d_txx_
00003 #define vimt_gaussian_pyramid_builder_2d_txx_
00004
00005
00006
00007
00008
00009 #include "vimt_gaussian_pyramid_builder_2d.h"
00010
00011 #include <vcl_cstdlib.h>
00012 #include <vcl_string.h>
00013
00014 #include <vcl_cassert.h>
00015 #include <vnl/vnl_math.h>
00016 #include <vil/algo/vil_gauss_reduce.h>
00017 #include <vimt/vimt_image_pyramid.h>
00018 #include <vimt/vimt_crop.h>
00019
00020
00021
00022 template<class T>
00023 vimt_gaussian_pyramid_builder_2d<T>::vimt_gaussian_pyramid_builder_2d()
00024 : max_levels_(99),filter_width_(5)
00025 {
00026 set_min_size(5, 5);
00027 }
00028
00029
00030
00031 template<class T>
00032 vimt_gaussian_pyramid_builder_2d<T>::~vimt_gaussian_pyramid_builder_2d()
00033 {
00034 }
00035
00036
00037
00038
00039 template<class T>
00040 void vimt_gaussian_pyramid_builder_2d<T>::set_max_levels(int max_l)
00041 {
00042 if (max_l<1)
00043 {
00044 vcl_cerr<<"vimt_gaussian_pyramid_builder_2d<T>::setMaxLevels() ";
00045 vcl_cerr<<"Must be >=1\n";
00046 vcl_abort();
00047 }
00048 max_levels_ = max_l;
00049 }
00050
00051
00052 template<class T>
00053 int vimt_gaussian_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_gaussian_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_gaussian_pyramid_builder_2d<T>::scale_step() const
00071 {
00072 return 2.0;
00073 }
00074
00075
00076 template<class T>
00077 void vimt_gaussian_pyramid_builder_2d<T>::set_filter_width(unsigned w)
00078 {
00079 assert(w==3 || w==5);
00080 filter_width_ = w;
00081 }
00082
00083
00084
00085 template<class T>
00086 void vimt_gaussian_pyramid_builder_2d<T>::gauss_reduce(const vimt_image_2d_of<T>& src_im,
00087 vimt_image_2d_of<T>& dest_im) const
00088 {
00089 switch (filter_width_)
00090 {
00091 case (3):
00092 vil_gauss_reduce_121(src_im.image(),dest_im.image());
00093 break;
00094 case (5):
00095 vil_gauss_reduce(src_im.image(),dest_im.image(),work_im_.image());
00096 break;
00097 default:
00098 vcl_cerr<<"vimt_gaussian_pyramid_builder_2d<T>::gauss_reduce() "
00099 <<"cannot cope with filter width of "<<filter_width_<<'\n';
00100 vcl_abort();
00101 }
00102
00103
00104 vimt_transform_2d scaling;
00105 scaling.set_zoom_only(0.5,0,0);
00106 dest_im.set_world2im(scaling * src_im.world2im());
00107 }
00108
00109
00110
00111 template<class T>
00112 void vimt_gaussian_pyramid_builder_2d<T>::empty_pyr(vimt_image_pyramid& im_pyr) const
00113 {
00114 for (int i=0; i<im_pyr.n_levels();++i)
00115 delete im_pyr.data()[i];
00116 }
00117
00118
00119
00120 template<class T>
00121 void vimt_gaussian_pyramid_builder_2d<T>::check_pyr(vimt_image_pyramid& im_pyr, int n_levels) const
00122 {
00123 const int got_levels = im_pyr.n_levels();
00124 if (got_levels >= n_levels && im_pyr(0).is_class(work_im_.is_a()))
00125 {
00126 if (im_pyr.n_levels()==n_levels) return;
00127 else
00128 {
00129 for (int i=n_levels;i<got_levels;++i)
00130 delete im_pyr.data()[i];
00131 }
00132 im_pyr.data().resize(n_levels);
00133 return;
00134 }
00135
00136 im_pyr.resize(n_levels,vimt_image_2d_of<T>());
00137 }
00138
00139
00140
00141 template<class T>
00142 void vimt_gaussian_pyramid_builder_2d<T>::build(vimt_image_pyramid& image_pyr,
00143 const vimt_image& im) const
00144 {
00145
00146 assert(im.is_class(work_im_.is_a()));
00147
00148 const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00149
00150 int ni = base_image.image().ni();
00151 int nj = base_image.image().nj();
00152
00153
00154
00155 int s = 1;
00156 int max_levels = 1;
00157 while ((ni/(2*s)>=int(minXSize_)) && (nj/(2*s)>=int(minYSize_)))
00158 {
00159 max_levels++;
00160 s*=2;
00161 }
00162
00163 if (max_levels>max_levels_)
00164 max_levels=max_levels_;
00165
00166
00167 check_pyr(image_pyr,max_levels);
00168
00169 vimt_image_2d_of<T>& im0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(0));
00170
00171
00172 im0 = vimt_crop(base_image,0,ni,0,nj);
00173
00174 int i;
00175 for (i=1;i<max_levels;i++)
00176 {
00177 vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(i));
00178 vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00179
00180 gauss_reduce(im_i1,im_i0);
00181 }
00182
00183
00184 vgl_point_2d<double> c0(0.5*(ni-1),0.5*(nj-1));
00185 vgl_point_2d<double> c1 = c0 + vgl_vector_2d<double> (1,1);
00186 vimt_transform_2d im2world = base_image.world2im().inverse();
00187 vgl_vector_2d<double> dw = im2world(c1) - im2world(c0);
00188
00189 double base_pixel_width = dw.length()/vnl_math::sqrt2;
00190 double scale_step = 2.0;
00191
00192 image_pyr.set_widths(base_pixel_width,scale_step);
00193 }
00194
00195
00196
00197
00198 template<class T>
00199 void vimt_gaussian_pyramid_builder_2d<T>::extend(vimt_image_pyramid& image_pyr) const
00200 {
00201
00202 assert(image_pyr(0).is_class(work_im_.is_a()));
00203
00204 assert(image_pyr.scale_step() == scale_step());
00205
00206 vimt_image_2d_of<T>& im_base = static_cast<vimt_image_2d_of<T>&>( image_pyr(0));
00207 int ni = im_base.image().ni();
00208 int nj = im_base.image().nj();
00209
00210
00211
00212 double s = 1;
00213 int max_levels = 1;
00214 while ((ni/(scale_step()*s)>=minXSize_) && (nj/(scale_step()*s)>=minYSize_))
00215 {
00216 max_levels++;
00217 s*=scale_step();
00218 }
00219
00220 if (max_levels>max_levels_)
00221 max_levels=max_levels_;
00222
00223
00224 int oldsize = image_pyr.n_levels();
00225 if (oldsize<max_levels)
00226 {
00227 image_pyr.data().resize(max_levels);
00228
00229 int i;
00230 for (i=oldsize;i<max_levels;++i)
00231 image_pyr.data()[i] = new vimt_image_2d_of<T>;
00232
00233 for (i=oldsize;i<max_levels;i++)
00234 {
00235 vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>( image_pyr(i));
00236 vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00237
00238 gauss_reduce(im_i1,im_i0);
00239 }
00240 }
00241 }
00242
00243
00244
00245
00246 #if 0
00247 template<class T>
00248 vcl_string vimt_gaussian_pyramid_builder_2d<T>::is_a() const
00249 {
00250 return vcl_string("vimt_gaussian_pyramid_builder_2d<T>");
00251 }
00252 #endif
00253
00254
00255
00256 template<class T>
00257 bool vimt_gaussian_pyramid_builder_2d<T>::is_class(vcl_string const& s) const
00258 {
00259 return s==vimt_gaussian_pyramid_builder_2d<T>::is_a() || vimt_image_pyramid_builder::is_class(s);
00260 }
00261
00262
00263
00264 template<class T>
00265 short vimt_gaussian_pyramid_builder_2d<T>::version_no() const
00266 {
00267 return 2;
00268 }
00269
00270
00271
00272 template<class T>
00273 vimt_image_pyramid_builder* vimt_gaussian_pyramid_builder_2d<T>::clone() const
00274 {
00275 return new vimt_gaussian_pyramid_builder_2d<T>(*this);
00276 }
00277
00278
00279
00280 template<class T>
00281 void vimt_gaussian_pyramid_builder_2d<T>::print_summary(vcl_ostream&) const
00282 {
00283 }
00284
00285
00286
00287 template<class T>
00288 void vimt_gaussian_pyramid_builder_2d<T>::b_write(vsl_b_ostream& bfs) const
00289 {
00290 vsl_b_write(bfs,version_no());
00291 vsl_b_write(bfs,max_levels_);
00292 vsl_b_write(bfs,filter_width_);
00293 }
00294
00295
00296
00297 template<class T>
00298 void vimt_gaussian_pyramid_builder_2d<T>::b_read(vsl_b_istream& bfs)
00299 {
00300 if (!bfs) return;
00301
00302 short version;
00303 vsl_b_read(bfs,version);
00304 switch (version)
00305 {
00306
00307 case (2):
00308 vsl_b_read(bfs,max_levels_);
00309 vsl_b_read(bfs,filter_width_);
00310 break;
00311 default:
00312 vcl_cerr << "I/O ERROR: vimt_gaussian_pyramid_builder_2d<T>::b_read(vsl_b_istream&)\n";
00313 vcl_cerr << " Unknown version number "<< version << "\n";
00314 bfs.is().clear(vcl_ios::badbit);
00315 return;
00316 }
00317 }
00318
00319 #define VIMT_GAUSSIAN_PYRAMID_BUILDER_2D_INSTANTIATE(T) \
00320 VCL_DEFINE_SPECIALIZATION vcl_string vimt_gaussian_pyramid_builder_2d<T >::is_a() const \
00321 { return vcl_string("vimt_gaussian_pyramid_builder_2d<" #T ">"); }\
00322 template class vimt_gaussian_pyramid_builder_2d<T >
00323
00324 #endif // vimt_gaussian_pyramid_builder_2d_txx_