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