00001 #include "bsol_distance_histogram.h"
00002
00003
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
00012 bsol_distance_histogram::bsol_distance_histogram()
00013 {
00014 delta_ = 0;
00015 }
00016
00017
00018
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
00075 bsol_distance_histogram::~bsol_distance_histogram()
00076 {
00077 }
00078
00079
00080
00081
00082
00083
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
00117
00118 double bsol_distance_histogram::interpolate_peak(int initial_peak)
00119 {
00120
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);
00135 double d2f = 0.5*(fplus+fminus-2.0*fzero);
00136 if (vcl_fabs(d2f)<1.0e-8)
00137 return bin_values_[initial_peak];
00138
00139 double root = -0.5*df/d2f;
00140
00141
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
00152 return result;
00153 }
00154
00155
00156
00157
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
00164 int init = 0, start = 1, down =2 , up=3, s_peak1= 4, down2 = 5, up2 = 6,
00165 s_peak2 = 7, fail=8;
00166
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
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
00189 if (state==start)
00190 {
00191
00192 if (bin_counts_[i]<=v)
00193 {
00194 state = down;
00195
00196 tr = min_peak_height_ratio*v;
00197 v=bin_counts_[i];
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
00210
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
00221 upi1 = i;
00222 }
00223 v = bin_counts_[i];
00224 continue;
00225 }
00226 }
00227
00228 if (state==up)
00229 {
00230
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
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
00256
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
00266 upi2 = i;
00267 }
00268 v = bin_counts_[i];
00269 continue;
00270 }
00271
00272
00273
00274 if (state==up2)
00275 {
00276
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;
00342 vcl_cout << "Distance Histogram\n";
00343
00344 double max_cnt = h.max_count();
00345 if (!max_cnt)
00346 return os;
00347
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 }