contrib/brl/bseg/brip/brip_max_scale_response.txx
Go to the documentation of this file.
00001 #ifndef brip_max_scale_response_txx_
00002 #define brip_max_scale_response_txx_
00003 
00004 #include "brip_max_scale_response.h"
00005 #include <vcl_cassert.h>
00006 #include <vcl_cmath.h>
00007 #include <vcl_iomanip.h>
00008 #include <vil/vil_convert.h>
00009 #include <vil/vil_resample_bilin.h>
00010 #include <brip/brip_vil_float_ops.h>
00011 
00012 template <class T>
00013 brip_max_scale_response<T>::
00014 brip_max_scale_response( vcl_vector<vil_image_view<T> > const& pyramid)
00015 {
00016   unsigned nlevels = pyramid.size();
00017   assert(nlevels>0);
00018   pyramid_scales_.push_back(1.0f);
00019   vil_image_view<float> lview;
00020   if (pyramid[0].nplanes()>1)
00021     vil_convert_planes_to_grey(pyramid[0], lview);
00022   else {
00023     vil_image_view_base_sptr v = new vil_image_view<T>(pyramid[0]);
00024     lview = vil_convert_cast(float(), v);
00025   }
00026   grey_pyramid_.push_back(lview);
00027   unsigned ni = pyramid[0].ni(), nj = pyramid[0].nj();
00028   float nif = static_cast<float>(ni), njf = static_cast<float>(nj);
00029   float diag0 = vcl_sqrt(nif*nif + njf*njf);
00030   for (unsigned level = 1; level<nlevels; ++level){
00031     if (pyramid[level].nplanes()>1)
00032       vil_convert_planes_to_grey(pyramid[level], lview);
00033     else {
00034       vil_image_view_base_sptr v = new vil_image_view<T>(pyramid[level]);
00035       lview = vil_convert_cast(float(), v);
00036     }
00037     grey_pyramid_.push_back(lview);
00038     ni = lview.ni(); nj = lview.nj();
00039     nif = static_cast<float>(ni); njf = static_cast<float>(nj);
00040     float diag = vcl_sqrt(nif*nif + njf*njf);
00041     float scale = diag0/diag;
00042     pyramid_scales_.push_back(scale);
00043   }
00044   this->compute_trace_pyramid();
00045 }
00046 
00047 template <class T>
00048 brip_max_scale_response<T>::
00049 brip_max_scale_response( vil_image_view<T> const& base_image,
00050                          double scale_ratio,
00051                          double max_scale )
00052 {
00053   vil_image_view<float> basef;
00054   if (base_image.nplanes()>1)
00055     vil_convert_planes_to_grey(base_image, basef);
00056   else {
00057     vil_image_view_base_sptr v = new vil_image_view<T>(base_image);
00058     basef = vil_convert_cast(float(), v);
00059   }
00060   // compute half octave scale intervals
00061   float scale = 1.0;
00062   if (scale_ratio>max_scale)
00063     scale_ratio = max_scale;
00064   while (scale<=static_cast<float>(max_scale))
00065   {
00066     pyramid_scales_.push_back(scale);
00067     scale*=static_cast<float>(scale_ratio);
00068   }
00069   grey_pyramid_.push_back(basef);
00070   unsigned nlevels = pyramid_scales_.size();
00071   for (unsigned level = 1; level<nlevels; ++level)
00072   {
00073     float s = pyramid_scales_[level];
00074     float s1 = pyramid_scales_[level-1];
00075     vil_image_view<T> img1 = grey_pyramid_[level-1];
00076     unsigned nil1 = img1.ni(), nilj = img1.nj();
00077     unsigned nil =  static_cast<unsigned>(nil1*s1/s),
00078       njl = static_cast<unsigned>(nilj*s1/s);
00079     vil_image_view<T> dec_img;
00080     vil_resample_bilin(img1, dec_img, nil, njl);
00081     grey_pyramid_.push_back(dec_img);
00082   }
00083   this->compute_trace_pyramid();
00084 }
00085 
00086 template <class T>
00087 vcl_vector<vil_image_view<T> > brip_max_scale_response<T>::
00088 image_pyramid(vil_image_view<T> const& base)
00089 {
00090   vcl_vector<vil_image_view<T> > temp;
00091   temp.push_back(base);
00092   unsigned nlevels = pyramid_scales_.size();
00093   assert(nlevels>0);
00094   for (unsigned level = 1; level<nlevels; ++level)
00095   {
00096     float s = pyramid_scales_[level];
00097     float s1 = pyramid_scales_[level-1];
00098     vil_image_view<T> img1 = temp[level-1];
00099     unsigned nil1 = img1.ni(), nilj = img1.nj();
00100     unsigned nil =  static_cast<unsigned>(nil1*s1/s),
00101       njl = static_cast<unsigned>(nilj*s1/s);
00102     vil_image_view<T> dec_img;
00103     vil_resample_bilin(img1, dec_img, nil, njl);
00104     temp.push_back(dec_img);
00105   }
00106   return temp;
00107 }
00108 
00109 template <class T>
00110 void brip_max_scale_response<T>::compute_trace_pyramid()
00111 {
00112   unsigned nlevels = grey_pyramid_.size();
00113   for (unsigned level = 0; level<nlevels; ++level)
00114   {
00115     unsigned ni = grey_pyramid_[level].ni(), nj = grey_pyramid_[level].nj();
00116     vil_image_view<float> lview;
00117     if (ni<=5||nj<=5) {
00118       lview.set_size(ni, nj);
00119       lview.fill(0.0f);
00120       trace_.push_back(lview);
00121       continue;
00122     }
00123     vil_image_view<float> temp = grey_pyramid_[level];
00124     vil_image_view<float> smooth = brip_vil_float_ops::gaussian(temp, 0.75, temp(0,0));
00125 #ifdef DEBUG
00126     vcl_cout << "Input at level " << level << '\n';
00127     for (unsigned j = 0; j<smooth.nj(); ++j){
00128       for (unsigned i = 0; i<smooth.nj(); ++i)
00129         vcl_cout << vcl_setprecision(2) << vcl_fixed << smooth(i,j) << ' ';
00130       vcl_cout <<'\n';
00131     }
00132 #endif
00133     const unsigned radius = 2;
00134     vil_image_view<float> tr =
00135       brip_vil_float_ops::trace_grad_matrix_NxN(smooth, radius);
00136     trace_.push_back(tr);
00137 #ifdef DEBUG
00138     vcl_cout << "Level " << level << '\n';
00139     for (unsigned j = 0; j<tr.nj(); ++j){
00140       for (unsigned i = 0; i<tr.nj(); ++i)
00141         vcl_cout << 10*tr(i,j) << ' ';
00142       vcl_cout <<'\n';
00143     }
00144 #endif
00145   }
00146   trace_valid_ = true;
00147 }
00148 
00149 //find the closest integral pixel location in an image with
00150 //the specified scale ratio to the image with location i.
00151 static unsigned loci(unsigned i, float scale_ratio)
00152 {
00153   float pos = scale_ratio*(float)i;
00154   unsigned ival = static_cast<unsigned>(pos+0.5f);
00155   return ival;
00156 }
00157 
00158 template <class T>
00159 vcl_vector<vil_image_view<float> >
00160 brip_max_scale_response<T>::scale_pyramid()
00161 {
00162   vcl_vector<vil_image_view<float> > temp, junk;
00163   if (!trace_valid_)
00164     return temp;
00165   vil_image_view<float> sbase = this->scale_base();
00166   unsigned ni = sbase.ni(), nj = sbase.nj();
00167 #ifdef DEBUG
00168   vcl_cout << "Printing scale base\n";
00169   for (unsigned j = 0; j<nj; ++j){
00170     for (unsigned i = 0; i<ni; ++i)
00171       vcl_cout << static_cast<unsigned>(sbase(i,j)) << ' ';
00172     vcl_cout <<'\n';
00173   }
00174 #endif
00175   unsigned nlevels = pyramid_scales_.size();
00176   float sc0 = pyramid_scales_[0];
00177   temp.resize(nlevels);
00178   temp[0]=sbase;
00179   for (unsigned level = 1; level<nlevels; ++level)
00180   {
00181     float sc = pyramid_scales_[level];
00182     float ratio = sc0/sc;
00183     unsigned nil = trace_[level].ni(), njl = trace_[level].nj();
00184     vil_image_view<float> sl(nil, njl);
00185     sl.fill(0.0f);
00186     for (unsigned bj = 0; bj<nj; ++bj){
00187       unsigned j = loci(bj, ratio);
00188       if (j>=njl) j=njl-1;
00189       for (unsigned bi = 0; bi<ni; ++bi) {
00190         unsigned i = loci(bi, ratio);
00191         if (i>=nil) i=nil-1;
00192         if (sbase(bi,bj)>sl(i,j))
00193           sl(i,j)=sbase(bi, bj);
00194       }
00195     }
00196     temp[level]=sl;
00197   }
00198   return temp;
00199 }
00200 
00201 
00202 template <class T>
00203 vcl_vector<vil_image_view<vxl_byte> >
00204 brip_max_scale_response<T>::mask_pyramid()
00205 {
00206   vcl_vector<vil_image_view<vxl_byte> > temp;
00207   if (!trace_valid_)
00208     return temp;
00209   vcl_vector<vil_image_view<float> > scales = this->scale_pyramid();
00210   unsigned nlevels = scales.size();
00211   for (unsigned level = 0; level<nlevels; ++level)
00212   {
00213     float cur_scale = pyramid_scales_[level];
00214     unsigned ni = scales[level].ni(), nj = scales[level].nj();
00215     vil_image_view<vxl_byte> mask(ni,nj);
00216     mask.fill(0);
00217 
00218     for (unsigned j = 0; j<nj; ++j)
00219       for (unsigned i = 0; i<ni; ++i)
00220         if (scales[level](i,j)==cur_scale)
00221           mask(i,j) = 255;
00222     temp.push_back(mask);
00223   }
00224 
00225   return temp;
00226 }
00227 
00228 
00229 template <class T>
00230 vil_image_view<float>
00231 brip_max_scale_response<T>::scale_base()
00232 {
00233   vil_image_view<float> temp;
00234   if (!trace_valid_)
00235     this->compute_trace_pyramid();
00236   if (!trace_valid_)
00237     return temp;
00238   unsigned nlevels = trace_.size();
00239   unsigned ni = trace_[0].ni(), nj = trace_[0].nj();
00240   unsigned bni = ni, bnj = nj;
00241   vil_image_view<float> base_tr;
00242   base_tr.deep_copy(trace_[0]);
00243   vil_image_view<float> base_sc(ni, nj);
00244   float sc0 = pyramid_scales_[0];
00245   base_sc.fill(sc0);
00246   for (unsigned level = 1; level<nlevels; ++level)
00247   {
00248     float sc = pyramid_scales_[level];
00249     float ratio = sc0/sc;
00250     vil_image_view<float>& trl = trace_[level];
00251     ni = trl.ni(); nj = trl.nj();
00252     for (unsigned bj = 0; bj<bnj; ++bj){
00253       unsigned j = loci(bj, ratio);
00254       if (j>=nj) j=nj-1;
00255       for (unsigned bi = 0; bi<bni; ++bi)
00256       {
00257         unsigned i = loci(bi, ratio);
00258         if (i>=ni) i=ni-1;
00259         if (trl(i,j)>base_tr(bi,bj)){
00260           base_tr(bi, bj)=trl(i,j);
00261           base_sc(bi, bj)=sc;
00262         }
00263       }
00264     }
00265   }
00266   return base_sc;
00267 }
00268 
00269 // Macro to perform manual instantiations
00270 #define BRIP_MAX_SCALE_RESPONSE(T) \
00271 template class brip_max_scale_response<T >
00272 
00273 #endif // brip_max_scale_response_txx_