Go to the documentation of this file.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 #ifdef DEBUG
00152 vcl_cout << "interpolated distance " << result << '\n';
00153 #endif // DEBUG
00154 return result;
00155 }
00156
00157
00158
00159
00160
00161 bool bsol_distance_histogram::
00162 distance_peaks(double& peak1, double& peak2, double min_peak_height_ratio)
00163 {
00164 int nbins = bin_counts_.size();
00165
00166 int init = 0, start = 1, down =2 , up=3, s_peak1= 4, down2 = 5, up2 = 6,
00167 s_peak2 = 7, fail=8;
00168
00169 int state=init;
00170 int upi1=0, upi2=0;
00171 double v=0;
00172 double tr=0, peak1_bin_counts=0;
00173 double start_distance = 0;
00174 for (int i = 0; i<nbins&&state!=fail&&state!=s_peak2; i++)
00175 {
00176 #ifdef DEBUG
00177 vcl_cout << "State[" << state << "], D = " << bin_values_[i]
00178 << " C = "<< bin_counts_[i] << " srt_d = " << start_distance
00179 << " v = "<< v << '\n';
00180 #endif
00181
00182 if (state==init)
00183 if (bin_counts_[i]>0)
00184 {
00185 v = bin_counts_[i];
00186 state = start;
00187 start_distance = 0;
00188 continue;
00189 }
00190
00191 if (state==start)
00192 {
00193
00194 if (bin_counts_[i]<=v)
00195 {
00196 state = down;
00197
00198 tr = min_peak_height_ratio*v;
00199 v=bin_counts_[i];
00200 continue;
00201 }
00202 else
00203 {
00204 state = start;
00205 v=bin_counts_[i];
00206 start_distance = bin_values_[i];
00207 continue;
00208 }
00209 }
00210
00211
00212
00213 if (state==down)
00214 {
00215 if (bin_counts_[i]>tr)
00216 {
00217 if (bin_counts_[i]<=v)
00218 state = down;
00219 else
00220 {
00221 state = up;
00222
00223 upi1 = i;
00224 }
00225 v = bin_counts_[i];
00226 continue;
00227 }
00228 }
00229
00230 if (state==up)
00231 {
00232
00233 if (bin_counts_[i]<=v)
00234 {
00235 state = s_peak1;
00236 peak1_bin_counts = bin_counts_[upi1];
00237 tr = min_peak_height_ratio*peak1_bin_counts;
00238 }
00239 else
00240 {
00241 upi1 = i;
00242 state = up;
00243 }
00244 v = bin_counts_[i];
00245 continue;
00246 }
00247
00248 if (state==s_peak1)
00249 {
00250 if (bin_counts_[i]<=peak1_bin_counts)
00251 state = down2;
00252 else
00253 state = fail;
00254 v = bin_counts_[i];
00255 continue;
00256 }
00257
00258
00259 if (state==down2)
00260 if (bin_counts_[i]>tr)
00261 {
00262 if (bin_counts_[i]<=v)
00263 state = down2;
00264 else
00265 {
00266 state = up2;
00267
00268 upi2 = i;
00269 }
00270 v = bin_counts_[i];
00271 continue;
00272 }
00273
00274
00275
00276 if (state==up2)
00277 {
00278
00279 if (bin_counts_[i]<=v)
00280 {
00281 state = s_peak2;
00282 }
00283 else
00284 {
00285 upi2 = i;
00286 state = up2;
00287 }
00288 v = bin_counts_[i];
00289 continue;
00290 }
00291 }
00292 if (state==up2||state==s_peak2)
00293 {
00294 peak1 = this->interpolate_peak(upi1)-start_distance;
00295 peak2 = this->interpolate_peak(upi2)-start_distance;
00296 return true;
00297 }
00298 return false;
00299 }
00300
00301 double bsol_distance_histogram::min_val() const
00302 {
00303 int nbins = bin_values_.size();
00304 if (!nbins)
00305 return 0;
00306 return bin_values_[0];
00307 }
00308
00309 double bsol_distance_histogram::max_val() const
00310 {
00311 int nbins = bin_values_.size();
00312 if (!nbins)
00313 return 0;
00314 return bin_values_[nbins-1];
00315 }
00316
00317 double bsol_distance_histogram::min_count() const
00318 {
00319 int nbins = bin_counts_.size();
00320 if (!nbins)
00321 return 0;
00322 double min_cnt = bin_counts_[0];
00323 for (int i = 1; i<nbins; i++)
00324 if (bin_counts_[i]<min_cnt)
00325 min_cnt = bin_counts_[i];
00326 return min_cnt;
00327 }
00328
00329 double bsol_distance_histogram::max_count() const
00330 {
00331 int nbins = bin_counts_.size();
00332 if (!nbins)
00333 return 0;
00334 double max_cnt = bin_counts_[0];
00335 for (int i = 1; i<nbins; i++)
00336 if (bin_counts_[i]>max_cnt)
00337 max_cnt = bin_counts_[i];
00338 return max_cnt;
00339 }
00340
00341 vcl_ostream& operator << (vcl_ostream& os, const bsol_distance_histogram& h)
00342 {
00343 int nchars = 25;
00344 vcl_cout << "Distance Histogram\n";
00345
00346 double max_cnt = h.max_count();
00347 if (!max_cnt)
00348 return os;
00349
00350 vcl_vector<double> const& vals = h.values();
00351 vcl_vector<double> const& cnts = h.counts();
00352 for (unsigned int i=0; i<vals.size(); ++i)
00353 {
00354 double val = vals[i];
00355 vcl_cout << val << '|';
00356 double cnt = cnts[i];
00357 int c = int(cnt*nchars/max_cnt);
00358 for (int k = 0; k<c; k++)
00359 vcl_cout << '*';
00360 vcl_cout << '\n';
00361 }
00362 return os;
00363 }