contrib/gel/vifa/vifa_int_faces_adj_attr.cxx
Go to the documentation of this file.
00001 // This is gel/vifa/vifa_int_faces_adj_attr.cxx
00002 #include "vifa_int_faces_adj_attr.h"
00003 
00004 vifa_int_faces_adj_attr::
00005 vifa_int_faces_adj_attr(void)
00006   : vifa_int_faces_attr(),
00007     closure_valid_(false),
00008     seed_(NULL),
00009     seed_attr_(NULL),
00010     depth_(BAD_DEPTH)
00011 {
00012   init();
00013   ComputeAttributes();
00014 }
00015 
00016 vifa_int_faces_adj_attr::
00017 vifa_int_faces_adj_attr(vtol_intensity_face_sptr     seed,
00018                         int                          depth,
00019                         int                          size_filter,
00020                         vdgl_fit_lines_params*       fitter_params,
00021                         vifa_group_pgram_params*     gpp_s,
00022                         vifa_group_pgram_params*     gpp_w,
00023                         vifa_coll_lines_params*      cpp,
00024                         vifa_norm_params*            np,
00025                         vifa_int_face_attr_factory*  factory,
00026                         float                        junk_area_percentage)
00027   : vifa_int_faces_attr(fitter_params, gpp_s, gpp_w, cpp, np, factory),
00028     closure_valid_(false),
00029     seed_(seed),
00030     seed_attr_(NULL),
00031     depth_(depth),
00032     size_filter_(size_filter),
00033     junk_area_percentage_(junk_area_percentage),
00034     junk_count_(0)
00035 {
00036   init();
00037   ComputeAttributes();
00038 }
00039 
00040 vifa_int_faces_adj_attr::
00041 vifa_int_faces_adj_attr(vtol_intensity_face_sptr     seed,
00042                         int                          depth,
00043                         iface_list&                  neighborhood,
00044                         int                          size_filter,
00045                         vdgl_fit_lines_params*       fitter_params,
00046                         vifa_group_pgram_params*     gpp_s,
00047                         vifa_group_pgram_params*     gpp_w,
00048                         vifa_coll_lines_params*      cpp,
00049                         vifa_norm_params*            np,
00050                         vifa_int_face_attr_factory*  factory,
00051                         float                        junk_area_percentage)
00052   : vifa_int_faces_attr(neighborhood, fitter_params, gpp_s, gpp_w, cpp, np, factory),
00053     closure_valid_(false), // still need to filter on size!
00054     seed_(seed),
00055     seed_attr_(NULL),
00056     depth_(depth),
00057     size_filter_(size_filter),
00058     junk_area_percentage_(junk_area_percentage),
00059     junk_count_(0)
00060 {
00061   init();
00062   ComputeAttributes();
00063 }
00064 
00065 void vifa_int_faces_adj_attr::
00066 SetSeed(vtol_intensity_face_sptr  seed)
00067 {
00068   seed_ = seed;
00069   closure_valid_ = false;
00070   seed_attr_ = factory_new_attr(seed_);
00071 }
00072 
00073 iface_list& vifa_int_faces_adj_attr::
00074 GetFaces()
00075 {
00076   if (!closure_valid_)
00077   {
00078     faces_.clear();
00079     this->compute_closure();
00080   }
00081 
00082   return faces_;
00083 }
00084 
00085 // Caller must delete returned list when finished
00086 iface_list*  vifa_int_faces_adj_attr::
00087 GetFaceList()
00088 {
00089   if (!closure_valid_)
00090   {
00091     faces_.clear();
00092     this->compute_closure();
00093   }
00094 
00095   iface_list* v = new iface_list;
00096   for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00097   {
00098     v->push_back(*f);
00099   }
00100 
00101   return v;
00102 }
00103 
00104 bool vifa_int_faces_adj_attr::
00105 ComputeAttributes()
00106 {
00107   if (!closure_valid_)
00108     this->compute_closure();
00109 
00110   if (vifa_int_faces_attr::ComputeAttributes())
00111   {
00112     // Seed is not included in faces_ or attribute histograms
00113     seed_attr_ = factory_new_attr(seed_);
00114     vifa_int_face_attr*  seed_attr_ptr = seed_attr_.ptr();
00115 
00116     // Compute ratio of seed to neighbors for each hist attribute
00117     for (int i = 0; i < this->NumHistAttributes(); i++)
00118     {
00119       float  seed_val = (seed_attr_ptr->*(attr_get_funcs[i]))();
00120 
00121       // Instead of x/y, compute (x+1)/(y+1) since y may be near zero
00122 
00123       float  hist_mean = GetMeanAttr(i);
00124       if (hist_mean < attr_min_vals[i])
00125         hist_mean = attr_min_vals[i];
00126       mean_ratios_[i] = (seed_val + 1) / (hist_mean + 1);
00127 
00128       float  hist_min = GetMinAttr(i);
00129       if (hist_min < attr_min_vals[i])
00130         hist_min = attr_min_vals[i];
00131       min_ratios_[i] = (seed_val + 1) / (hist_min + 1);
00132     }
00133 
00134     attributes_valid_ = true;
00135   }
00136 
00137   return valid_p();
00138 }
00139 
00140 int vifa_int_faces_adj_attr::
00141 NeighborhoodSize()
00142 {
00143   compute_closure();
00144   return faces_.size();
00145 }
00146 
00147 // Populate a vector containing all attributes, including inherited ones.
00148 bool vifa_int_faces_adj_attr::
00149 GetAttributes(vcl_vector<float>& attrs)
00150 {
00151   if (vifa_int_faces_attr::GetAttributes(attrs))
00152     return this->vifa_int_faces_adj_attr::GetNativeAttributes(attrs);
00153   else
00154     return false;
00155 }
00156 
00157 // Append the attribute names to a vector in the same order as
00158 // GetAttributes.  KEEP IN SYNC WITH GetAttributes!!!
00159 void vifa_int_faces_adj_attr::
00160 GetAttributeNames(vcl_vector<vcl_string>& names)
00161 {
00162   vifa_int_faces_attr::GetAttributeNames(names);
00163 
00164   for (int i = 0; i < NUM_HIST_ATTRIBUTES; i++)
00165   {
00166     vcl_string  name(attr_names[i]);
00167     names.push_back("ratio" + name);
00168   }
00169 
00170   for (int i = 0; i < NUM_HIST_ATTRIBUTES; i++)
00171   {
00172     vcl_string  name(attr_names[i]);
00173     names.push_back("minRatio" + name);
00174   }
00175 }
00176 
00177 // Populate a vector containing attributes native to this class (not
00178 // inherited).  KEEP IN SYNC WITH GETNAMES ABOVE!
00179 // Assumes that
00180 bool vifa_int_faces_adj_attr::
00181 GetNativeAttributes(vcl_vector<float>& attrs)
00182 {
00183   if (!this->ComputeAttributes())
00184   {
00185     vcl_cerr << "Couldn't compute group adj attributes?\n";
00186     return false;
00187   }
00188 
00189   for (int i = 0; i < this->NumHistAttributes(); i++)
00190   {
00191     attrs.push_back(this->GetRatioAttr(i));
00192   }
00193 
00194   for (int i = 0; i < this->NumHistAttributes(); i++)
00195   {
00196     attrs.push_back(this->GetMinRatioAttr(i));
00197   }
00198 
00199   // what about Collinearity()???
00200 
00201   return true;
00202 }
00203 
00204 bool vifa_int_faces_adj_attr::
00205 compute_closure()
00206 {
00207 //  vcl_cout << " In ifsaa::compute_closure()...\n";
00208 
00209   if (!closure_valid_)
00210   {
00211     if (faces_.empty())
00212     {
00213 //      vcl_cout << "faces_ is empty -- rebuilding\n";
00214 
00215       if ((seed_) && (depth_ != BAD_DEPTH))
00216       {
00217         // Temporarily add the seed to the list (front), preventing the
00218         // neighborhood construction from adding it back accidentally.
00219         faces_.push_back(seed_);
00220 
00221         // Build the neighborhood (recursively)
00222         this->compute_closure_step(0, seed_);
00223 
00224         // Remove the seed, leaving the true neighborhood
00225         faces_.erase(faces_.begin());
00226       }
00227     }
00228 
00229 //    vcl_cout << faces_.size() << " face(s)" << endl;
00230 
00231     float    original_area = 0;
00232     float    junk_area = 0;
00233     int      original_nbrhood_size = faces_.size();
00234     float    area_threshold = (seed_->Npix() * junk_area_percentage_);
00235     iface_list  keep_faces;
00236     for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00237     {
00238       original_area += (*f)->Npix();
00239 
00240       if ((*f)->Npix() >= area_threshold)
00241         keep_faces.push_back(*f);
00242       else
00243       {
00244         junk_count_++;
00245         junk_area += (*f)->Npix();
00246       }
00247     }
00248 
00249 //    vcl_cout << keep_faces.size() << " keep_face(s)" << endl;
00250 
00251     faces_ = keep_faces;
00252     junk_percent_ = (float)junk_count_ / original_nbrhood_size;
00253     junk_area_ratio_ = junk_area / original_area;
00254     closure_valid_ = true;
00255   }
00256 
00257 #if 0
00258   vcl_cout << "Final faces_: " << faces_.size() << vcl_endl;
00259 
00260   for (iface_iterator f = faces_.begin(); f != faces_.end(); ++f)
00261     vcl_cout << "  (" << (*f)->Xo() << ", " << (*f)->Yo() << "), "
00262              << (*f)->Npix() << " pixels\n";
00263 #endif
00264 
00265 //  vcl_cout << "Leaving ifsaa::compute_closure()\n";
00266 
00267   return closure_valid_;
00268 }
00269 
00270 float vifa_int_faces_adj_attr::
00271 Collinearity()
00272 {
00273   compute_closure();
00274   get_collinear_lines();
00275 
00276   float    u_len = 0.0f;
00277   float    w_len = 0.0f;
00278   float    coll = 0.0f;
00279   edge_list edges; seed_->edges(edges);
00280 
00281   for (edge_iterator  ei = edges.begin(); ei != edges.end(); ei++)
00282   {
00283     vtol_edge_2d*  e = (*ei)->cast_to_edge_2d();
00284 
00285     if (e)
00286     {
00287       vifa_coll_lines_sptr  clr = get_line_along_edge(e);
00288 
00289       if (clr)
00290       {
00291         u_len += float(e->curve()->length());
00292         w_len += float(clr->spanning_length());
00293       }
00294     }
00295   }
00296 
00297   if (u_len > 0.0f)
00298     coll = w_len / u_len;
00299 
00300   return coll;
00301 }
00302 
00303 // Get the ratio of a vifa_int_face_attr attribute to the seed.
00304 float vifa_int_faces_adj_attr::
00305 GetRatioAttr(int attr_index)
00306 {
00307   return mean_ratios_[attr_index];
00308 }
00309 
00310 // Get the ratio of the seed's vifa_int_face_attr to the minimum neighbor
00311 float vifa_int_faces_adj_attr::
00312 GetMinRatioAttr(int attr_index)
00313 {
00314   return min_ratios_[attr_index];
00315 }
00316 
00317 void vifa_int_faces_adj_attr::
00318 init()
00319 {
00320   junk_percent_ = 0.0f;
00321   junk_area_ratio_ = 0.0f;
00322 
00323   int    n = NumHistAttributes();
00324   mean_ratios_.reserve(n);
00325   min_ratios_.reserve(n);
00326 
00327   // initialize to -1.
00328   for (int i = 0; i < n; i++)
00329     mean_ratios_[i] = min_ratios_[i] = -1;
00330 }
00331 
00332 bool vifa_int_faces_adj_attr::
00333 add_unique_face(iface_list&               facelist,
00334                 vtol_intensity_face_sptr  face,
00335                 int                       size_filter)
00336 {
00337   for (iface_iterator check = facelist.begin();
00338        check != facelist.end(); ++check)
00339   {
00340     if ((check->ptr()->Xo() == face->Xo()) &&
00341         (check->ptr()->Yo() == face->Yo()))
00342       return false;
00343   }
00344 
00345   if (face->Npix() >= size_filter)
00346   {
00347     facelist.push_back(face);
00348     return true;
00349   }
00350 
00351   return false;
00352 }
00353 
00354 void vifa_int_faces_adj_attr::
00355 compute_closure_step(int                       current_depth,
00356                      vtol_intensity_face_sptr  seed)
00357 {
00358 #ifdef CCS_DEBUG
00359   vcl_cout << "ccs: depth " << current_depth << " of " << depth_;
00360 
00361   if (seed)
00362     vcl_cout << " at seed " << seed->Xo() << ", " << seed->Yo();
00363   else
00364     vcl_cout << " with null seed";
00365 #endif
00366 
00367   if ((current_depth >= depth_) || (!seed))
00368   {
00369 #ifdef CCS_DEBUG
00370     vcl_cout << "...bailing\n";
00371 #endif
00372     return;
00373   }
00374 #ifdef CCS_DEBUG
00375   else
00376     vcl_cout << vcl_endl;
00377 #endif
00378 
00379   // Get all the faces adjacent to the seed face
00380   iface_list*  adj_faces = get_adjacent_faces(seed);
00381   if (adj_faces)
00382   {
00383     // For each adjacent face...
00384     iface_iterator fi = adj_faces->begin();
00385     for (; fi != adj_faces->end(); fi++)
00386     {
00387       vtol_intensity_face_sptr  adj_face_sptr = (*fi);
00388 
00389       // Try to add the adjacent face to the master face list
00390       if (this->add_unique_face(faces_, adj_face_sptr, size_filter_))
00391       {
00392         // It's a new face, so recursively find its neighbors
00393         this->compute_closure_step(current_depth + 1, adj_face_sptr);
00394       }
00395     }
00396 
00397     delete adj_faces;
00398   }
00399   else
00400     vcl_cerr << "vifsaa::compute_closure_step(): No adj. faces found!\n";
00401 }
00402 
00403 vtol_intensity_face_sptr vifa_int_faces_adj_attr::
00404 get_adjacent_face_at_edge(vtol_intensity_face_sptr&  known_face,
00405                           vtol_edge_2d*              e)
00406 {
00407   vtol_intensity_face_sptr  adj_face = 0;
00408   face_list faces; e->faces(faces);
00409 
00410   // Expect only one or two intensity faces for 2-D case
00411   if (faces.size() == 2)
00412   {
00413     vtol_intensity_face*  f1 = faces[0]->cast_to_intensity_face();
00414     vtol_intensity_face*  f2 = faces[1]->cast_to_intensity_face();
00415 
00416     if (f1 && f2 && *known_face == *f1)
00417       adj_face = f2;
00418     else if (f1 && f2 && *known_face == *f2)
00419       adj_face = f1;
00420     else
00421     {
00422       // Known face does not contain the
00423       // given edge -- leave result NULL
00424     }
00425   }
00426 
00427   return adj_face;
00428 }
00429 
00430 iface_list* vifa_int_faces_adj_attr::
00431 get_adjacent_faces(vtol_intensity_face_sptr&  known_face)
00432 {
00433   iface_list*    faces = NULL;
00434 
00435   if (known_face.ptr())
00436   {
00437     edge_list edges; known_face->edges(edges);
00438     faces = new iface_list;
00439 
00440     for (edge_iterator ei = edges.begin(); ei != edges.end(); ei++)
00441     {
00442       vtol_edge_2d* e = (*ei)->cast_to_edge_2d();
00443       if (e)
00444       {
00445         vtol_intensity_face_sptr  other_f =
00446           this->get_adjacent_face_at_edge(known_face, e);
00447 
00448         if (other_f.ptr())
00449           this->add_unique_face(*faces, other_f, 0);
00450       }
00451     }
00452   }
00453 
00454   return faces;
00455 }