00001
00002 #ifndef vimt_gaussian_pyramid_builder_2d_general_txx_
00003 #define vimt_gaussian_pyramid_builder_2d_general_txx_
00004
00005
00006
00007
00008
00009 #include "vimt_gaussian_pyramid_builder_2d_general.h"
00010 #include <vcl_cmath.h>
00011 #include <vcl_cassert.h>
00012 #include <vcl_string.h>
00013 #include <vcl_iostream.h>
00014 #include <vil/algo/vil_gauss_reduce.h>
00015 #include <vimt/vimt_image_pyramid.h>
00016 #include <vimt/vimt_crop.h>
00017
00018
00019
00020 template <class T>
00021 vimt_gaussian_pyramid_builder_2d_general<T>::vimt_gaussian_pyramid_builder_2d_general():
00022 scale_params_(2.0)
00023 {}
00024
00025
00026 template <class T>
00027 vimt_gaussian_pyramid_builder_2d_general<T>::vimt_gaussian_pyramid_builder_2d_general(double scale_step):
00028 scale_params_(scale_step)
00029 {}
00030
00031
00032
00033 template <class T>
00034 vimt_gaussian_pyramid_builder_2d_general<T>::~vimt_gaussian_pyramid_builder_2d_general()
00035 {}
00036
00037
00038 template <class T>
00039 void vimt_gaussian_pyramid_builder_2d_general<T>::set_scale_step(double scaleStep)
00040 {
00041 scale_params_ = vil_gauss_reduce_params(scaleStep);
00042 }
00043
00044
00045
00046 template <class T>
00047 void vimt_gaussian_pyramid_builder_2d_general<T>::build(
00048 vimt_image_pyramid& im_pyr,
00049 const vimt_image& im) const
00050 {
00051 assert(im.is_class(vimt_image_2d_of<T>().is_a()));
00052
00053 const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(im);
00054
00055 int ni = base_image.image().ni();
00056 int nj = base_image.image().nj();
00057
00058
00059
00060 double s = scale_step();
00061 int maxlevels = 1;
00062 while (((unsigned int)(ni/s+0.5)>=this->min_x_size()) &&
00063 ((unsigned int)(nj/s+0.5)>=this->min_y_size()))
00064 {
00065 maxlevels++;
00066 s *= scale_step();
00067 }
00068
00069 if (maxlevels > this->max_levels())
00070 maxlevels=this->max_levels();
00071
00072 worka_.set_size(ni,nj);
00073 workb_.set_size(ni,nj);
00074
00075
00076 this->check_pyr(im_pyr,maxlevels);
00077
00078 vimt_image_2d_of<T>& im0 = static_cast<vimt_image_2d_of<T>&>(im_pyr(0));
00079
00080
00081 im0 = vimt_crop(base_image,0,ni,0,nj);
00082
00083 s = scale_step();
00084 for (int i=1;i<maxlevels;i++)
00085 {
00086 vimt_image_2d_of<T>& dest = static_cast<vimt_image_2d_of<T>&>(im_pyr(i));
00087 const vimt_image_2d_of<T>& src = static_cast<const vimt_image_2d_of<T>&>(im_pyr(i-1));
00088
00089 s*=scale_step();
00090 vil_gauss_reduce_general(src.image(), dest.image(), worka_, workb_, scale_params_);
00091
00092
00093 vimt_transform_2d scaling;
00094
00095
00096
00097 const double init_x = 0.5 * (src.image().ni() - 1 - (dest.image().ni()-1)*scale_params_.scale_step());
00098 const double init_y = 0.5 * (src.image().nj() - 1 - (dest.image().nj()-1)*scale_params_.scale_step());
00099
00100 scaling.set_zoom_only(1/scale_params_.scale_step(),-init_x,-init_y);
00101 dest.set_world2im(scaling * src.world2im());
00102 }
00103
00104
00105 vgl_point_2d<double> c0(0.5*(ni-1),0.5*(nj-1));
00106 vgl_point_2d<double> c1 = c0 + vgl_vector_2d<double> (1,1);
00107 vimt_transform_2d im2world = base_image.world2im().inverse();
00108 vgl_vector_2d<double> dw = im2world(c1) - im2world(c0);
00109
00110 double base_pixel_width = vcl_sqrt(0.5*(dw.x()*dw.x() + dw.y()*dw.y()));
00111
00112 im_pyr.set_widths(base_pixel_width,scale_step());
00113 }
00114
00115
00116
00117
00118
00119 template<class T>
00120 void vimt_gaussian_pyramid_builder_2d_general<T>::extend(vimt_image_pyramid& image_pyr) const
00121 {
00122
00123 assert(image_pyr(0).is_class(vimt_image_2d_of<T>().is_a()));
00124
00125 assert(image_pyr.scale_step() == scale_step());
00126
00127 const vimt_image_2d_of<T>& base_image = static_cast<const vimt_image_2d_of<T>&>(image_pyr(0));
00128
00129
00130 const int ni = base_image.image().ni();
00131 const int nj = base_image.image().nj();
00132
00133
00134
00135 double s = scale_step();
00136 int maxlevels = 1;
00137 while (((unsigned int)(ni/s+0.5) >= this->min_x_size()) &&
00138 ((unsigned int)(nj/s+0.5) >= this->min_y_size()))
00139 {
00140 maxlevels++;
00141 s*=scale_step();
00142 }
00143
00144 if (maxlevels > this->max_levels())
00145 maxlevels=this->max_levels();
00146
00147 worka_.set_size(ni,nj);
00148 workb_.set_size(ni,nj);
00149
00150
00151 int oldsize = image_pyr.n_levels();
00152 if (oldsize<maxlevels)
00153 {
00154 image_pyr.data().resize(maxlevels);
00155
00156 s = vcl_pow(scale_step(), oldsize);
00157 for (int i=oldsize;i<maxlevels;i++)
00158 {
00159 image_pyr.data()[i] = new vimt_image_2d_of<T>;
00160 vimt_image_2d_of<T>& im_i0 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i));
00161 vimt_image_2d_of<T>& im_i1 = static_cast<vimt_image_2d_of<T>&>(image_pyr(i-1));
00162 im_i0.image().set_size((unsigned)(ni/s+0.5),(unsigned)(nj/s+0.5),
00163 im_i1.image().nplanes());
00164
00165 s*=scale_step();
00166 vil_gauss_reduce_general(im_i1.image(), im_i0.image(), worka_, workb_, scale_params_);
00167 }
00168 }
00169 }
00170
00171
00172
00173 #if 0
00174 template <class T>
00175 vcl_string vimt_gaussian_pyramid_builder_2d_general<T>::is_a() const
00176 {
00177 return vcl_string("vimt_gaussian_pyramid_builder_2d_general<T>");
00178 }
00179 #endif // 0
00180
00181
00182 template <class T>
00183 bool vimt_gaussian_pyramid_builder_2d_general<T>::is_class(vcl_string const& s) const
00184 {
00185 return s==vimt_gaussian_pyramid_builder_2d_general<T>::is_a() ||
00186 vimt_gaussian_pyramid_builder_2d<T>::is_class(s);
00187 }
00188
00189
00190
00191 template <class T>
00192 short vimt_gaussian_pyramid_builder_2d_general<T>::version_no() const
00193 {
00194 return 1;
00195 }
00196
00197
00198
00199 template <class T>
00200 vimt_image_pyramid_builder* vimt_gaussian_pyramid_builder_2d_general<T>::clone() const
00201 {
00202 return new vimt_gaussian_pyramid_builder_2d_general(*this);
00203 }
00204
00205
00206
00207 template <class T>
00208 void vimt_gaussian_pyramid_builder_2d_general<T>::print_summary(vcl_ostream& os) const
00209 {
00210 vimt_gaussian_pyramid_builder_2d<T>::print_summary(os);
00211 }
00212
00213
00214
00215 template <class T>
00216 void vimt_gaussian_pyramid_builder_2d_general<T>::b_write(vsl_b_ostream& bfs) const
00217 {
00218 vsl_b_write(bfs,version_no());
00219 vimt_gaussian_pyramid_builder_2d<T>::b_write(bfs);
00220 vsl_b_write(bfs,scale_step());
00221 }
00222
00223
00224
00225 template <class T>
00226 void vimt_gaussian_pyramid_builder_2d_general<T>::b_read(vsl_b_istream& bfs)
00227 {
00228 if (!bfs) return;
00229
00230 short version;
00231 vsl_b_read(bfs,version);
00232 double scale;
00233
00234 switch (version)
00235 {
00236 case 1:
00237 vimt_gaussian_pyramid_builder_2d<T>::b_read(bfs);
00238
00239 vsl_b_read(bfs,scale);
00240 set_scale_step(scale);
00241 break;
00242 default:
00243 vcl_cerr << "I/O ERROR: vimt_gaussian_pyramid_builder_2d_general<T>::b_read(vsl_b_istream&)\n"
00244 << " Unknown version number "<< version << '\n';
00245 bfs.is().clear(vcl_ios::badbit);
00246 return;
00247 }
00248 }
00249
00250 #define VIMT_GAUSSIAN_PYRAMID_BUILDER_2D_GENERAL_INSTANTIATE(T) \
00251 VCL_DEFINE_SPECIALIZATION vcl_string vimt_gaussian_pyramid_builder_2d_general<T >::is_a() const \
00252 { return vcl_string("vimt_gaussian_pyramid_builder_2d_general<" #T ">"); }\
00253 template class vimt_gaussian_pyramid_builder_2d_general<T >
00254
00255
00256 #endif // vimt_gaussian_pyramid_builder_2d_general_txx_