contrib/gel/vifa/vifa_int_face_attr.cxx
Go to the documentation of this file.
00001 // This is gel/vifa/vifa_int_face_attr.cxx
00002 #include "vifa_int_face_attr.h"
00003 //:
00004 // \file
00005 
00006 #include <vtol/vtol_intensity_face.h>
00007 
00008 vifa_int_face_attr::
00009 vifa_int_face_attr(vdgl_fit_lines_params*  fitter_params,
00010                    vifa_group_pgram_params*  gpp,
00011                    vifa_group_pgram_params*  gpp_w,
00012                    vifa_norm_params*    np) :
00013   vifa_int_face_attr_common(fitter_params, gpp, gpp_w, 0, np),
00014   face_(NULL),
00015   cached_min_(0.0f),
00016   cached_max_(0.0f),
00017   cached_mean_(0.0f),
00018   cached_var_(0.0f),
00019   npobj_(0)
00020 {
00021 }
00022 
00023 vifa_int_face_attr::
00024 vifa_int_face_attr(vtol_intensity_face_sptr f,
00025                    vdgl_fit_lines_params*  fitter_params,
00026                    vifa_group_pgram_params*  gpp,
00027                    vifa_group_pgram_params*  gpp_w,
00028                    vifa_norm_params*    np) :
00029   vifa_int_face_attr_common(fitter_params, gpp, gpp_w, 0, np),
00030   face_(f),
00031   cached_min_(0.0f),
00032   cached_max_(0.0f),
00033   cached_mean_(0.0f),
00034   cached_var_(0.0f),
00035   cached_2_parallel_(-1),
00036   cached_4_parallel_(-1),
00037   cached_80_parallel_(-1),
00038   npobj_(0)
00039 {
00040   attributes_valid_ = this->ComputeAttributes();
00041 }
00042 
00043 vifa_int_face_attr::
00044 ~vifa_int_face_attr()
00045 {
00046   delete npobj_;
00047 }
00048 
00049 
00050 // ------------------------------------------------------------
00051 // Data access & computation for non-attributes
00052 //
00053 
00054 void vifa_int_face_attr::
00055 SetFace(vtol_intensity_face_sptr  f)
00056 {
00057   face_ = f;
00058   delete npobj_;
00059   npobj_ = 0;
00060   attributes_valid_ = this->ComputeAttributes();
00061 }
00062 
00063 edge_2d_list& vifa_int_face_attr::
00064 GetEdges()
00065 {
00066   // Don't compute again if already there
00067   if (!edges_.empty())
00068     return edges_;
00069 
00070   if (!face_)
00071   {
00072     vcl_cerr << "vifa_int_face_attr::GetFaces(): face_ is not set\n";
00073     return edges_;
00074   }
00075 
00076   edge_list  fedges; face_->edges(fedges);
00077   for (edge_iterator eli = fedges.begin(); eli != fedges.end(); eli++)
00078   {
00079     vtol_edge_2d_sptr  e = (*eli)->cast_to_edge_2d();
00080     if (e)
00081       edges_.push_back(e);
00082   }
00083 
00084   return edges_;
00085 }
00086 
00087 
00088 // ------------------------------------------------------------
00089 // Public functional methods
00090 //
00091 
00092 bool vifa_int_face_attr::
00093 ComputeAttributes()
00094 {
00095   ComputeCacheValues();
00096   attributes_valid_ = true;
00097   return this->valid_p();
00098 }
00099 
00100 // Populate a vector containing all attributes, including inherited
00101 // ones.
00102 bool vifa_int_face_attr::
00103 GetAttributes(vcl_vector<float>&  attrs)
00104 {
00105   // no inherited attributes
00106   return this->vifa_int_face_attr::GetNativeAttributes(attrs);
00107 }
00108 
00109 // Append the names of the attributes in the same order as in
00110 // GetNativeAttributes.  KEEP THEM IN SYNC!
00111 void vifa_int_face_attr::
00112 GetAttributeNames(vcl_vector<vcl_string>&  names)
00113 {
00114   names.push_back("IntMax");
00115   names.push_back("IntMin");
00116   names.push_back("IntMean");
00117   names.push_back("IntVar");
00118   names.push_back("Area");
00119   names.push_back("AspectRatio");
00120   names.push_back("PerimeterLength");
00121   names.push_back("WeightedPerimeterLength");
00122   names.push_back("Complexity");
00123   names.push_back("WeightedComplexity");
00124   names.push_back("StrongParallel");
00125   names.push_back("WeakParallel");
00126   names.push_back("TwoPeakParallel");
00127   names.push_back("FourPeakParallel");
00128   names.push_back("EightyPercentParallel");
00129 }
00130 
00131 // Populate a vector containing attributes native to this class (not
00132 // inherited).  SYNC ADDITIONS TO THIS WITH THE NAMES FUNCTION ABOVE!
00133 bool vifa_int_face_attr::
00134 GetNativeAttributes(vcl_vector<float>& attrs)
00135 {
00136   if (!this->ComputeAttributes())
00137   {
00138     vcl_cerr << "Couldn't compute single face attributes?\n";
00139     return false;
00140   }
00141 
00142   attrs.push_back(this->IntMax());
00143   attrs.push_back(this->IntMin());
00144   attrs.push_back(this->IntMean());
00145   attrs.push_back(this->IntVar());
00146   attrs.push_back(this->Area());
00147   attrs.push_back(this->AspectRatio());
00148   attrs.push_back(this->PerimeterLength());
00149   attrs.push_back(this->WeightedPerimeterLength());
00150   attrs.push_back(this->Complexity());
00151   attrs.push_back(this->WeightedComplexity());
00152   attrs.push_back(this->StrongParallelSal());
00153   attrs.push_back(this->WeakParallelSal());
00154   attrs.push_back(this->TwoPeakParallel());
00155   attrs.push_back(this->FourPeakParallel());
00156   attrs.push_back(this->EightyPercentParallel());
00157   return true;
00158 }
00159 
00160 // ------------------------------------------------------------
00161 // Individual attribute computation
00162 //
00163 
00164 float vifa_int_face_attr::
00165 AspectRatio()
00166 {
00167   if (aspect_ratio_ < 0)
00168     aspect_ratio_ = face_->AspectRatio();
00169 
00170   return aspect_ratio_;
00171 }
00172 
00173 float vifa_int_face_attr::
00174 PerimeterLength()
00175 {
00176   if (peri_length_ < 0)
00177     peri_length_ = float(face_->perimeter());
00178 
00179   return peri_length_;
00180 }
00181 
00182 float vifa_int_face_attr::
00183 WeightedPerimeterLength()
00184 {
00185   if (weighted_peri_length_ < 0)
00186   {
00187     // Block-copied from intensity face rather than undergo the pain
00188     // of adding a "weighted" boolean parameter
00189     edge_list edges; face_->edges(edges);
00190     double p = 0.0;
00191     double intensity_sum = 1.0;
00192 
00193     for (edge_iterator eit = edges.begin(); eit != edges.end(); eit++)
00194     {
00195       vtol_edge_2d_sptr  e = (*eit)->cast_to_edge_2d();
00196       if (e)
00197       {
00198         // Leave at default of 1.0 if no adjacent face
00199         double  int_grad = get_contrast_across_edge(e->cast_to_edge(), 1.0);
00200         p += e->curve()->length() * int_grad;
00201         intensity_sum += int_grad;
00202       }
00203     }
00204 
00205     weighted_peri_length_ = float(p / intensity_sum);
00206   }
00207 
00208   return weighted_peri_length_;
00209 }
00210 
00211 float vifa_int_face_attr::
00212 Complexity()
00213 {
00214   float  area = this->Area();
00215   float  len = this->PerimeterLength();
00216 
00217   if (complexity_ < 0 && len >= 0 && area > 0)
00218     complexity_ = len * len / area;
00219 
00220   return complexity_;
00221 }
00222 
00223 float vifa_int_face_attr::
00224 WeightedComplexity()
00225 {
00226   float  area = this->Area();
00227   float  len = this->WeightedPerimeterLength();
00228 
00229   if (weighted_complexity_ < 0 && len >= 0 && area > 0)
00230     weighted_complexity_ = len * len / area;
00231 
00232   return weighted_complexity_;
00233 }
00234 
00235 float vifa_int_face_attr::
00236 TwoPeakParallel()
00237 {
00238   if (cached_2_parallel_ < 0)
00239   {
00240     SetNP();
00241 
00242     for (int i = 0; i < 1; i++)
00243     {
00244       float  max_angle, std_dev, scale;
00245       npobj_->map_gaussian(max_angle, std_dev, scale);
00246       npobj_->remove_gaussian(max_angle, std_dev, scale);
00247     }
00248 
00249     cached_2_parallel_ = npobj_->area();
00250   }
00251 
00252   return cached_2_parallel_;
00253 }
00254 
00255 float vifa_int_face_attr::
00256 FourPeakParallel()
00257 {
00258   if (cached_4_parallel_ < 0)
00259   {
00260     SetNP();
00261 
00262     for (int i = 0; i < 3; i++)
00263     {
00264       float  max_angle, std_dev, scale;
00265       npobj_->map_gaussian(max_angle, std_dev, scale);
00266       npobj_->remove_gaussian(max_angle, std_dev, scale);
00267     }
00268 
00269     cached_4_parallel_ = npobj_->area();
00270   }
00271 
00272   return cached_4_parallel_;
00273 }
00274 
00275 float vifa_int_face_attr::
00276 EightyPercentParallel()
00277 {
00278   if (cached_80_parallel_ < 0)
00279   {
00280     SetNP();
00281 
00282     for (int i=0; i < 20 && npobj_->area() > 0.3f; ++i)
00283     {
00284       float  max_angle, std_dev, scale;
00285       npobj_->map_gaussian(max_angle, std_dev, scale);
00286       npobj_->remove_gaussian(max_angle, std_dev, scale);
00287       cached_80_parallel_ = i;
00288     }
00289   }
00290 
00291   return float(cached_80_parallel_);
00292 }
00293 
00294 void vifa_int_face_attr::
00295 ComputeCacheValues()
00296 {
00297   float  real_min = face_->get_min();
00298   float  real_max = face_->get_max();
00299 
00300   // Sanity check -- can happen if face has 0 pixels...
00301   if (real_min > real_max)
00302   {
00303     real_min = 0.0f;
00304     real_max = 1.0f;  // Superstitious, probably could also be zero?
00305   }
00306 
00307   int        max_bins = int(real_max - real_min + 1);
00308   int        nbins = (face_->Npix() > max_bins) ? max_bins : face_->Npix();
00309   vifa_histogram  intensity_hist(nbins, real_min, real_max);
00310 
00311   for (int i = 0; i < face_->Npix(); i++)
00312   {
00313     float  pval = (face_->Ij())[i];
00314     intensity_hist.UpCount(pval);
00315   }
00316 
00317 #ifdef DEBUG
00318   vcl_cout << "vifa::ComputeCacheValues(): start dump:\n";
00319   intensity_hist.Print();
00320   vcl_cout << "LowClipVal: " << intensity_hist.LowClipVal(0.1) << vcl_endl
00321            << "HighClipVal: " << intensity_hist.LowClipVal(0.9) << vcl_endl
00322            << "face_->Io(): " << face_->Io() << vcl_endl
00323            << "face_->Npix(): " << face_->Npix() << vcl_endl;
00324   np_->print_info();
00325   vcl_cout << "vifa::ComputeCacheValues(): end dump\n";
00326 #endif
00327 
00328   cached_min_ = normalize_intensity(intensity_hist.LowClipVal(0.1f));
00329   cached_max_ = normalize_intensity(intensity_hist.LowClipVal(0.9f));
00330   cached_mean_ = normalize_intensity(face_->Io());
00331 
00332   float sum = 0.0f;
00333   const unsigned short*  pvals = face_->Ij();
00334 
00335   for (int i = 0; i < face_->Npix(); i++)
00336   {
00337     float  mapped_pval = normalize_intensity(pvals[i]);
00338     float  delta = mapped_pval - cached_mean_;
00339     sum += delta * delta;
00340   }
00341 
00342   cached_var_ = sum / face_->Npix();
00343 }
00344 
00345 void vifa_int_face_attr::
00346 SetNP()
00347 {
00348   if (npobj_)
00349     npobj_->reset();
00350   else
00351   {
00352     vcl_vector<vtol_intensity_face_sptr>  faces;
00353     faces.push_back(face_);
00354 
00355     static bool  contrast = true;
00356     npobj_ = new vifa_parallel(faces, contrast);
00357   }
00358 }