contrib/brl/bbas/bsol/bsol_distance_histogram.cxx

Go to the documentation of this file.
00001 #include "bsol_distance_histogram.h"
00002 //:
00003 // \file
00004 #include <vcl_cmath.h>
00005 #include <vcl_iostream.h>
00006 #include <vnl/vnl_math.h>
00007 #include <vnl/vnl_numeric_traits.h>
00008 #include <vgl/vgl_homg_line_2d.h>
00009 #include <vsol/vsol_line_2d.h>
00010 
00011 //: Constructors
00012 bsol_distance_histogram::bsol_distance_histogram()
00013 {
00014   delta_ = 0;
00015 }
00016 
00017 //------------------------------------------------------------------------
00018 //: set up the histogram with bin spacing defined by max_val and nbins.
00019 //------------------------------------------------------------------------
00020 bsol_distance_histogram::bsol_distance_histogram(int nbins, double max_val)
00021 {
00022   if (!nbins)
00023   {
00024     delta_=0;
00025     return;
00026   }
00027   bin_counts_.resize(nbins, 0.0);
00028   bin_values_.resize(nbins, 0.0);
00029   weights_.resize(nbins, 0.0);
00030   delta_ = max_val/nbins;
00031 }
00032 
00033 bsol_distance_histogram::
00034 bsol_distance_histogram(const int nbins,
00035                         vcl_vector<vsol_line_2d_sptr> const& lines)
00036 {
00037   if (!nbins)
00038   {
00039     delta_=0;
00040     return;
00041   }
00042   bin_counts_.resize(nbins, 0.0);
00043   bin_values_.resize(nbins, 0.0);
00044   weights_.resize(nbins, 0.0);
00045 
00046   int Nlines = lines.size();
00047   vcl_vector<vgl_homg_line_2d<double> > hlines;
00048   double dmin = vnl_numeric_traits<double>::maxval, dmax = -dmin;
00049   for (int i = 0; i<Nlines; i++)
00050   {
00051     hlines.push_back(lines[i]->vgl_hline_2d());
00052     hlines[i].normalize();
00053     double d = hlines[i].c();
00054     dmin = vnl_math_min(dmin, d);
00055     dmax = vnl_math_max(dmax, d);
00056   }
00057   delta_ = (dmax-dmin)/nbins;
00058 
00059   for (int i = 0; i<Nlines; i++)
00060   {
00061     double ci = hlines[i].c();
00062     double length_i = lines[i]->length();
00063     for (int j = i+1; j<Nlines; j++)
00064     {
00065       double cj = hlines[j].c();
00066       double length = lines[j]->length()+length_i;
00067       double D = vcl_fabs(ci-cj);
00068       this->up_count(D, length, length);
00069     }
00070   }
00071   this->normalize_distance();
00072 }
00073 
00074 //: Destructor
00075 bsol_distance_histogram::~bsol_distance_histogram()
00076 {
00077 }
00078 
00079 
00080 //---------------------------------------------------------------------
00081 //: normalized bin distance = (Sum_i length_i*dist_i)/(Sum_i length_i)
00082 //  Note distances can't be negative so the -1 flag indicates there
00083 //  was no count for that bin.
00084 //---------------------------------------------------------------------
00085 void bsol_distance_histogram::normalize_distance()
00086 {
00087   for (unsigned int k = 0; k<bin_counts_.size(); ++k)
00088   {
00089     if (weights_[k])
00090     {
00091       double val = bin_values_[k];
00092       double w = weights_[k];
00093       bin_values_[k]=val/w;
00094     }
00095     else
00096       bin_values_[k]=-1;
00097   }
00098 }
00099 
00100 void bsol_distance_histogram::up_count(const double value, const double count,
00101                                        const double weight)
00102 {
00103   double val = 0;
00104   bool inserted = false;
00105   for (unsigned int k = 0; k<bin_counts_.size()&&!inserted; ++k, val+=delta_)
00106     if (val>=value)
00107     {
00108       bin_counts_[k]+=count;
00109       bin_values_[k]+=value*weight;
00110       weights_[k]+=weight;
00111       inserted = true;
00112     }
00113 }
00114 
00115 //---------------------------------------------------------------
00116 //: refine the peak location using parabolic interpolation
00117 //
00118 double bsol_distance_histogram::interpolate_peak(int initial_peak)
00119 {
00120   //boundary conditions
00121   if (initial_peak<0)
00122     return 0;
00123   if (initial_peak==0)
00124     return bin_values_[0];
00125   int n = bin_values_.size();
00126   if (initial_peak==(n-1))
00127     return bin_values_[n-1];
00128   if (initial_peak>=n)
00129     return 0;
00130   double fminus = bin_counts_[initial_peak-1];
00131   double fzero = bin_counts_[initial_peak];
00132   double fplus = bin_counts_[initial_peak+1];
00133 
00134   double df = 0.5*(fplus-fminus);//first derivative
00135   double d2f = 0.5*(fplus+fminus-2.0*fzero);//second derivative
00136   if (vcl_fabs(d2f)<1.0e-8)
00137     return bin_values_[initial_peak];
00138 
00139   double root = -0.5*df/d2f;
00140 
00141   //interpolate the bin values within the appropriate interval
00142   double dminus = bin_values_[initial_peak-1];
00143   double dzero = bin_values_[initial_peak];
00144   double dplus = bin_values_[initial_peak+1];
00145 
00146   double result;
00147   if (root<0)
00148    result = (dzero*(1+root)-dminus*root);
00149   else
00150     result =  (dzero*(1-root)+dplus*root);
00151   //  vcl_cout << "interpolated distance " << result << '\n';
00152   return result;
00153 }
00154 
00155 //---------------------------------------------------------------
00156 //: There will typically be a large distance peak at small distances
00157 //  The second distance peak will correspond to periodic line segments
00158 //
00159 bool bsol_distance_histogram::
00160 distance_peaks(double& peak1, double& peak2, double min_peak_height_ratio)
00161 {
00162   int nbins = bin_counts_.size();
00163   //Peak search states
00164   int init = 0, start = 1, down =2 , up=3, s_peak1= 4, down2 = 5, up2 = 6,
00165     s_peak2 = 7, fail=8;
00166   //Initial state assignment
00167   int state=init;
00168   int upi1=0, upi2=0;
00169   double v=0;
00170   double tr=0, peak1_bin_counts=0;
00171   double start_distance = 0;
00172   for (int i = 0; i<nbins&&state!=fail&&state!=s_peak2; i++)
00173   {
00174 #ifdef DEBUG
00175     vcl_cout << "State[" << state << "], D = " << bin_values_[i]
00176              << " C = "<< bin_counts_[i] << " srt_d = " << start_distance
00177              << " v = "<< v << '\n';
00178 #endif
00179     //Begin the scan look for a value above 0
00180     if (state==init)
00181       if (bin_counts_[i]>0)
00182       {
00183         v = bin_counts_[i];
00184         state = start;
00185         start_distance = 0;
00186         continue;
00187       }
00188     //If we are in the start state set the threshold and move down.
00189     if (state==start)
00190     {
00191       //        if (bin_counts_[i]>0)
00192       if (bin_counts_[i]<=v)
00193       {
00194         state = down;
00195         //second peak should be a significant ratio of the starting value
00196         tr = min_peak_height_ratio*v;
00197         v=bin_counts_[i];    //population
00198         continue;
00199       }
00200       else
00201       {
00202         state = start;
00203         v=bin_counts_[i];
00204         start_distance = bin_values_[i];
00205         continue;
00206       }
00207     }
00208 
00209     // we are in the down state looking for a value above the
00210     // ratio threshold and is above the current v value.
00211     if (state==down)
00212     {
00213       if (bin_counts_[i]>tr)
00214       {
00215         if (bin_counts_[i]<=v)
00216           state = down;
00217         else
00218         {
00219           state = up;
00220           //upi1 is the location of the up state
00221           upi1 = i;
00222         }
00223         v = bin_counts_[i];
00224         continue;
00225       }
00226     }
00227     // we are moving up, waiting to capture a peak above the threshold
00228     if (state==up)
00229     {
00230       //        if (bin_counts_[i]>tr)
00231       if (bin_counts_[i]<=v)
00232       {
00233         state = s_peak1;
00234         peak1_bin_counts = bin_counts_[upi1];
00235         tr = min_peak_height_ratio*peak1_bin_counts;
00236       }
00237       else
00238       {
00239         upi1 = i;
00240         state = up;
00241       }
00242       v = bin_counts_[i];
00243       continue;
00244     }
00245     // we have just passed  peak 1
00246     if (state==s_peak1)
00247     {
00248       if (bin_counts_[i]<=peak1_bin_counts)
00249         state = down2;
00250       else
00251         state = fail;
00252       v = bin_counts_[i];
00253       continue;
00254     }
00255     // we are in the second down state looking for a value above the
00256     // ratio threshold and is above the current v value.
00257     if (state==down2)
00258       if (bin_counts_[i]>tr)
00259       {
00260         if (bin_counts_[i]<=v)
00261           state = down2;
00262         else
00263         {
00264           state = up2;
00265           //upi2 is the location of the up state
00266           upi2 = i;
00267         }
00268         v = bin_counts_[i];
00269         continue;
00270       }
00271 
00272     // we are moving up a second time, waiting to capture a peak
00273     // above the threshold
00274     if (state==up2)
00275     {
00276       //        if (bin_counts_[i]>tr)
00277       if (bin_counts_[i]<=v)
00278       {
00279         state = s_peak2;
00280       }
00281       else
00282       {
00283         upi2 = i;
00284         state = up2;
00285       }
00286       v = bin_counts_[i];
00287       continue;
00288     }
00289   }
00290   if (state==up2||state==s_peak2)
00291   {
00292     peak1 = this->interpolate_peak(upi1)-start_distance;
00293     peak2 = this->interpolate_peak(upi2)-start_distance;
00294     return true;
00295   }
00296   return false;
00297 }
00298 
00299 double bsol_distance_histogram::min_val() const
00300 {
00301   int nbins = bin_values_.size();
00302   if (!nbins)
00303     return 0;
00304   return bin_values_[0];
00305 }
00306 
00307 double bsol_distance_histogram::max_val() const
00308 {
00309   int nbins = bin_values_.size();
00310   if (!nbins)
00311     return 0;
00312   return bin_values_[nbins-1];
00313 }
00314 
00315 double bsol_distance_histogram::min_count() const
00316 {
00317   int nbins = bin_counts_.size();
00318   if (!nbins)
00319     return 0;
00320   double min_cnt = bin_counts_[0];
00321   for (int i = 1; i<nbins; i++)
00322     if (bin_counts_[i]<min_cnt)
00323       min_cnt = bin_counts_[i];
00324   return min_cnt;
00325 }
00326 
00327 double bsol_distance_histogram::max_count() const
00328 {
00329   int nbins = bin_counts_.size();
00330   if (!nbins)
00331     return 0;
00332   double max_cnt = bin_counts_[0];
00333   for (int i = 1; i<nbins; i++)
00334     if (bin_counts_[i]>max_cnt)
00335       max_cnt = bin_counts_[i];
00336   return max_cnt;
00337 }
00338 
00339 vcl_ostream& operator << (vcl_ostream& os, const bsol_distance_histogram& h)
00340 {
00341   int nchars = 25;//display resolution
00342   vcl_cout << "Distance Histogram\n";
00343   //get the maximum bin value
00344   double max_cnt = h.max_count();
00345   if (!max_cnt)
00346     return os;
00347   // forced to cast away const
00348   bsol_distance_histogram & hh = (bsol_distance_histogram&)h;
00349   vcl_vector<double>& vals = hh.values();
00350   vcl_vector<double>& cnts = hh.counts();
00351   for (unsigned int i=0; i<vals.size(); i++)
00352   {
00353     double val = vals[i];
00354     vcl_cout << val << '|';
00355     double cnt = cnts[i];
00356     int c = int(cnt*nchars/max_cnt);
00357     for (int k = 0; k<c; k++)
00358       vcl_cout << '*';
00359     vcl_cout << '\n';
00360   }
00361   return os;
00362 }

Generated on Sun Sep 7 05:20:15 2008 for contrib/brl/bbas/bsol by  doxygen 1.5.1