contrib/gel/vifa/vifa_parallel.cxx
Go to the documentation of this file.
00001 // This is gel/vifa/vifa_parallel.cxx
00002 #include "vifa_parallel.h"
00003 //:
00004 // \file
00005 #include <vnl/vnl_math.h>
00006 #include <vdgl/vdgl_digital_curve.h>
00007 #include <vsol/vsol_curve_2d.h>
00008 #include <vtol/vtol_edge_2d.h>
00009 #include <vtol/vtol_vertex_2d.h>
00010 #include <vtol/vtol_intensity_face.h>
00011 #include "vifa_gaussian.h"
00012 
00013 #ifdef DUMP
00014 #include <vul/vul_sprintf.h>
00015 #include <vcl_fstream.h>
00016 
00017 static int pass = 0;
00018 #endif
00019 
00020 const float n_sigma = 2.0;  // on either side of center
00021 
00022 
00023 vifa_parallel::
00024 vifa_parallel(iface_list&   faces,
00025               bool          contrast_weighted,
00026               vifa_parallel_params*  params) :
00027   vifa_parallel_params(params)
00028 {
00029   raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00030   float  range = max_angle - min_angle;
00031 
00032   for (iface_iterator ifi = faces.begin(); ifi != faces.end(); ++ifi)
00033   {
00034     edge_list edges; (*ifi)->edges(edges);
00035 
00036     for (edge_iterator ei = edges.begin(); ei != edges.end(); ei++)
00037     {
00038       vtol_edge_2d* e = (*ei)->cast_to_edge_2d();
00039 
00040       if (e)
00041       {
00042 #ifdef OLD_LINE_APPROX
00043         const vtol_vertex_2d*  v1 = e->v1()->cast_to_vertex_2d();
00044         const vtol_vertex_2d*  v2 = e->v2()->cast_to_vertex_2d();
00045         double dy = v1->y() - v2->y();
00046         double dx = v1->x() - v2->x();
00047         double length = 0.0;
00048 
00049         if (contrast_weighted)
00050         {
00051           vtol_intensity_face_sptr other_f = get_adjacent_iface(*ifi, e);
00052 
00053           if (other_f)
00054             length = vcl_sqrt((dx * dx) + (dy * dy))
00055                    * vcl_fabs((*ifi)->Io() - other_f->Io());
00056         }
00057 
00058         double  orientation = vcl_atan2(dy, dx) * vnl_math::deg_per_rad;
00059         if (orientation < 0)
00060           orientation += 180.0;
00061 
00062         float  theta = map_x(float(orientation));
00063         raw_h_->SetCount(theta, raw_h_->GetCount(theta) + float(length));
00064 #else
00065         vsol_curve_2d_sptr  c = e->curve();
00066 
00067         if (c)
00068         {
00069           vdgl_digital_curve*  dc = c->cast_to_vdgl_digital_curve();
00070 
00071           if (dc)
00072           {
00073             double l = dc->length();
00074 
00075             for (int i = 0; i < l; i++)
00076             {
00077               // Use parametric index representation (0 -- 1)
00078               double theta = dc->get_theta(i / l);
00079 #ifdef DEBUG
00080               vcl_cout << "raw theta: " << theta;
00081 #endif
00082               while (theta < min_angle)
00083                 theta += range;
00084 
00085               while (theta > max_angle)
00086                 theta -= range;
00087 #ifdef DEBUG
00088               vcl_cout << " to " << theta << vcl_endl;
00089 #endif
00090               raw_h_->UpCount(float(theta));
00091             }
00092           }
00093         }
00094 #endif  // OLD_LINE_APPROX
00095       }
00096     }
00097   }
00098 
00099   norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00100 }
00101 
00102 
00103 vifa_parallel::
00104 vifa_parallel(vcl_vector<float>&  pixel_orientations,
00105               vifa_parallel_params*  params) :
00106   vifa_parallel_params(params)
00107 {
00108   raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00109   float  range = max_angle - min_angle;
00110 
00111   for (vcl_vector<float>::iterator p = pixel_orientations.begin();
00112        p != pixel_orientations.end(); ++p)
00113   {
00114     float  theta = (*p);
00115 
00116     while (theta < min_angle)
00117     {
00118       theta += range;
00119     }
00120     while (theta > max_angle)
00121     {
00122       theta -= range;
00123     }
00124 
00125     raw_h_->UpCount(theta);
00126   }
00127 
00128   norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00129 }
00130 
00131 vifa_parallel::
00132 vifa_parallel(float  center_angle,
00133               float  std_dev)
00134 {
00135   raw_h_ = new vifa_histogram(nbuckets, min_angle, max_angle);
00136 
00137 #ifdef DEBUG
00138   vcl_cout << "vifa_parallel(): 0.5 is "<< raw_h_->GetValIndex(0.5) << vcl_endl;
00139 #endif
00140 
00141   vifa_gaussian  g(center_angle, std_dev);
00142   for (float i = min_angle; i < 2 * max_angle; i++)
00143   {
00144     float  v = g.pdf(i);
00145     float  vx = map_x(i);
00146 
00147     raw_h_->SetCount(vx, raw_h_->GetCount(vx) + v);
00148   }
00149 
00150   norm_h_ = vifa_parallel::normalize_histogram(raw_h_);
00151 }
00152 
00153 vifa_parallel::~vifa_parallel()
00154 {
00155   delete raw_h_;
00156   delete norm_h_;
00157 }
00158 
00159 void vifa_parallel::reset(void)
00160 {
00161   delete norm_h_;
00162   norm_h_ = normalize_histogram(raw_h_);
00163 }
00164 
00165 vifa_histogram* vifa_parallel::
00166 get_raw_hist(void)
00167 {
00168   return raw_h_;
00169 }
00170 
00171 vifa_histogram* vifa_parallel::
00172 get_norm_hist(void)
00173 {
00174   return norm_h_;
00175 }
00176 
00177 void vifa_parallel::
00178 map_gaussian(float&  max_angle,
00179              float&  std_dev,
00180              float&  scale)
00181 {
00182   bool    set_min_res_flag = true;
00183 
00184   const float  incr = 3.0;  // put me in the params!
00185   float    max_value;
00186   float    local_max_angle = find_peak(max_value);
00187   max_angle = 0.0;
00188   std_dev = 0.0;
00189   scale = 0.0;
00190 
00191   // Skip histograms that are empty
00192   if (local_max_angle != -1.0)
00193   {
00194     float  min_residual = 0.f; // dummy initialisation
00195 
00196     for (float j=-(n_sigma+1); j<=(n_sigma+1); j++)
00197     {
00198       float  new_center = map_x(local_max_angle + (j * incr));
00199       float local_std_dev = 0.0;  // degrees
00200 
00201       for (int i = 0; i < 5; i++)
00202       {
00203         local_std_dev += incr;
00204         vifa_gaussian  g(new_center, local_std_dev);
00205         float      g_max = g.pdf(new_center);
00206         float      local_scale = norm_h_->GetCount(new_center) /
00207                         g_max;
00208         // NOTE: local_scale could be zero if the histogram is 0 here...
00209 
00210 #ifdef DUMP
00211         char      buf[25];
00212         vul_sprintf(buf, "gauss-%d-%d-%d.dat", pass, (int)j, i);
00213         vcl_ofstream  gdump(buf);
00214 #endif
00215         // int    sample_count = 0;
00216         float  sample_sum = 0.0;
00217 
00218         for (float  dx = (-n_sigma * local_std_dev);
00219              dx <= (n_sigma * local_std_dev);
00220              dx += norm_h_->GetBucketSize())
00221         {
00222           float  vx = new_center + dx;
00223           float  e = g.pdf(vx) * local_scale;
00224           // e could be zero because of local_scale, see above
00225           float  x = map_x(vx);
00226           float  f = norm_h_->GetCount(x);
00227           if (f < 0)
00228           {
00229             f = 0;
00230           }
00231 
00232           float  diff = vcl_fabs(f - e);
00233 
00234 #ifdef DUMP
00235           gdump << x << ' ' << e << ' ' << diff << ' ' << vx << ' ' << f << vcl_endl;
00236 #endif
00237           if (e != 0.0)
00238           {
00239             sample_sum += ((diff * diff) / e);
00240             // sample_count++;
00241           }
00242         }
00243 
00244         // Set min_residual the first time thru
00245         if ((set_min_res_flag || sample_sum < min_residual) && sample_sum != 0)
00246         {
00247           set_min_res_flag = false;
00248           min_residual = sample_sum;
00249           std_dev = local_std_dev;
00250           max_angle = new_center;
00251           scale = local_scale;
00252 
00253 #ifdef DEBUG
00254           vcl_cout << "*** ";
00255 #endif
00256         }
00257 
00258 #ifdef DEBUG
00259         vcl_cout << j << " gaussian " << i << " residual "
00260                  << sample_sum << " sample count " << sample_count << vcl_endl;
00261 #endif
00262       }
00263     }
00264 
00265 #ifdef DEBUG
00266     vcl_cout << "best is at " << max_angle << " sd of " << std_dev
00267              << " scale " << scale << vcl_endl;
00268 #endif
00269 
00270 #ifdef DUMP
00271     pass++;
00272 #endif
00273   }
00274 }
00275 
00276 void vifa_parallel::
00277 remove_gaussian(float  max_angle,
00278                 float  std_dev,
00279                 float  scale)
00280 {
00281   // Skip if histogram is empty
00282   if (norm_h_->GetMaxCount() != 0.0)
00283   {
00284     vifa_gaussian  g(max_angle, std_dev);
00285     for (float  dx = (-n_sigma * std_dev);
00286          dx <= (n_sigma * std_dev);
00287          dx += norm_h_->GetBucketSize())
00288     {
00289       float  vx = max_angle + dx;
00290       float  e = g.pdf(vx) * scale;
00291       float  x = map_x(vx);
00292       float  f = norm_h_->GetCount(x);
00293 
00294       if (f >= 0)
00295       {
00296         float  new_val = ((f - e) < 0) ? 0 : (f - e);
00297 
00298 #ifdef DEBUG
00299         vcl_cout << "  --- " << x << ": " << f <<" to " << new_val << vcl_endl;
00300 #endif
00301 
00302         norm_h_->SetCount(x, new_val);
00303       }
00304       else
00305       {
00306         vcl_cerr << "  --- " << x << ": bad " <<
00307           norm_h_->GetValIndex(x) << vcl_endl;
00308       }
00309     }
00310   }
00311 }
00312 
00313 void vifa_parallel::
00314 snapshot(char* fname)
00315 {
00316   norm_h_->WritePlot(fname);
00317 }
00318 
00319 float vifa_parallel::
00320 area(void)
00321 {
00322   if (norm_h_->GetMaxCount() == 0.0)
00323   {
00324     // Return 0 area for empty histograms
00325     return 0.0;
00326   }
00327   else
00328   {
00329     return norm_h_->ComputeArea();
00330   }
00331 }
00332 
00333 float vifa_parallel::
00334 bin_variance(void)
00335 {
00336   float* counts = norm_h_->GetCounts();
00337   int    res = norm_h_->GetRes();
00338   float  sum = 0;
00339   float  sum2 = 0;
00340 
00341   for (int i = 0; i < res; i++)
00342   {
00343     sum += counts[i];
00344     sum2 += (counts[i] * counts[i]);
00345   }
00346 
00347   float mean = sum / res;
00348   float var = (sum2 / res) - (mean * mean);
00349 
00350   return var;
00351 }
00352 
00353 float vifa_parallel::
00354 map_x(float  raw_x)
00355 {
00356   float  range = max_angle - min_angle + 1;
00357 
00358   while (raw_x < min_angle)
00359   {
00360     raw_x += range;
00361   }
00362   while (raw_x > max_angle)
00363   {
00364     raw_x -= range;
00365   }
00366 
00367   return raw_x;
00368 }
00369 
00370 vifa_histogram* vifa_parallel::
00371 normalize_histogram(vifa_histogram* h)
00372 {
00373   vifa_histogram*  norm = new vifa_histogram(nbuckets, min_angle, max_angle);
00374   int        nbuckets = h->GetRes();
00375   float      area = h->ComputeArea();
00376   float*      x_vals = h->GetVals();
00377   float*      y_vals = h->GetCounts();
00378 
00379   for (int i = 0; i < nbuckets; i++)
00380   {
00381     float  new_area = y_vals[i] / area;
00382     norm->SetCount(x_vals[i], new_area);
00383   }
00384 
00385   return norm;
00386 }
00387 
00388 float vifa_parallel::
00389 find_peak(float&  max_value)
00390 {
00391   int    nbuckets = norm_h_->GetRes();
00392   float*  x_vals = norm_h_->GetVals();
00393   float*  y_vals = norm_h_->GetCounts();
00394   int    max_index = -1;
00395   max_value = -1;
00396 
00397   for (int i = 0; i < nbuckets; i++)
00398   {
00399     if (y_vals[i] > max_value)
00400     {
00401       max_index = i;
00402       max_value = y_vals[i];
00403     }
00404   }
00405 
00406   if (max_index == -1)
00407   {
00408     return -1;
00409   }
00410 
00411   max_value = y_vals[max_index];
00412   return x_vals[max_index];
00413 }
00414 
00415 vtol_intensity_face_sptr vifa_parallel::
00416 get_adjacent_iface(vtol_intensity_face_sptr  known_face,
00417                    vtol_edge_2d*         e)
00418 {
00419   vtol_intensity_face_sptr  adj_face = 0;
00420   face_list faces; e->faces(faces);
00421 
00422   // Expect only two intensity faces for 2-D case
00423   if (faces.size() == 2)
00424   {
00425     vtol_intensity_face* f1 = faces[0]->cast_to_intensity_face();
00426     vtol_intensity_face* f2 = faces[1]->cast_to_intensity_face();
00427 
00428     if (f1 && f2)
00429     {
00430       if (*known_face == *f1)
00431       {
00432         adj_face = f2;
00433       }
00434       else if (*known_face == *f2)
00435       {
00436         adj_face = f1;
00437       }
00438       else
00439       {
00440         // Known face does not contain the
00441         // given edge -- leave result NULL
00442       }
00443     }
00444   }
00445   return adj_face;
00446 }