Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

gevd_edgel_regions.cxx

Go to the documentation of this file.
00001 // This is gel/gevd/gevd_edgel_regions.cxx
00002 #include "gevd_edgel_regions.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_iostream.h>
00007 #include <vcl_cstdlib.h> // for vcl_abs(int)
00008 #include <vcl_cassert.h>
00009 #include <vcl_algorithm.h> // for vcl_sort() and vcl_find()
00010 
00011 #include <vtol/vtol_intensity_face.h>
00012 
00013 #include <vxl_config.h>
00014 #include <vil1/vil1_memory_image_of.h>
00015 #include <vcl_cmath.h>     // for sqrt()
00016 #include <vul/vul_timer.h>
00017 
00018 #include <vsol/vsol_box_2d.h>
00019 #include <vsol/vsol_box_2d_sptr.h>
00020 #include <vtol/vtol_edge.h>
00021 #include <vtol/vtol_edge_2d.h>
00022 #include <vtol/vtol_one_chain.h>
00023 #include <vtol/vtol_cycle_processor.h>
00024 
00025 #include <vdgl/vdgl_digital_curve.h>
00026 #include <vdgl/vdgl_edgel_chain.h>
00027 #include <vdgl/vdgl_interpolator.h>
00028 
00029 
00030 #define bytePixel(buf,x,y)   (*((unsigned char*)buf->GetElementAddr(x,y)))
00031 #define shortPixel(buf,x,y)  (*((short*)buf->GetElementAddr(x,y)))
00032 
00033 #if 0 // not ported to vxl
00034 //----------------------------------------------------------------
00035 //: cache debug info
00036 void edgel_regions::cache_bad_edges(CoolArrayP<Edge*>& bad_edges)
00037 {
00038   vcl_vector<Edge*> corrupt_edges;
00039   for (CoolArrayP<Edge*>::iterator eit = bad_edges.begin();
00040        eit != bad_edges.end(); eit++)
00041     corrupt_edges.push_back(*eit);
00042   corrupt_edges_.push_back(corrupt_edges);
00043 }
00044 
00045 void edgel_regions::cache_bad_edges(vcl_vector<Edge*>& bad_edges)
00046 {
00047   vcl_vector<Edge*> corrupt_edges;
00048   for (vcl_vector<Edge*>::iterator eit = bad_edges.begin();
00049        eit != bad_edges.end(); eit++)
00050     corrupt_edges.push_back(*eit);
00051   corrupt_edges_.push_back(corrupt_edges);
00052 }
00053 
00054 void edgel_regions::cache_bad_verts(CoolArrayP<Vertex*>& bad_verts)
00055 {
00056   vcl_vector<Vertex*> corrupt_verts;
00057   for (CoolArrayP<Vertex*>::iterator vit = bad_verts.begin();
00058        vit != bad_verts.end(); vit++)
00059     corrupt_verts.push_back(*vit);
00060   corrupt_vertices_.push_back(corrupt_verts);
00061 }
00062 #endif
00063 
00064 //--------------------------------------------------------
00065 //: compare function to be used with CoolList<float>::sort() [increasing]
00066 static int increasing_compare(unsigned int const&a, unsigned int const&b)
00067 {
00068   if (a > b) return 1;
00069   if (a < b) return -1;
00070   return 0;
00071 }
00072 
00073 //Print the region label array
00074 void gevd_edgel_regions::print_region_array()
00075 {
00076   vcl_cout << vcl_endl;
00077   for (unsigned int y = yo_; y<=yend_; y++)
00078   {
00079     vcl_cout << vcl_endl; // << setw(2);
00080     for (unsigned int x = xo_; x<=xend_; x++)
00081       if (region_label_array_[Y(y)][X(x)]==EDGE)
00082           //&&edge_boundary_array_[Y(y)][X(x)]->IsVertex()
00083         vcl_cout << "* ";
00084       else
00085         vcl_cout << region_label_array_[Y(y)][X(x)] << ' ';
00086   }
00087   vcl_cout << "\n\n\n";
00088 }
00089 
00090 //Print the contents of the forward equivalence index
00091 void gevd_edgel_regions::print_region_equivalence()
00092 {
00093   vcl_cout << vcl_endl << "Label Equivalence:\n"
00094            << "----------------\n";
00095   vcl_map<unsigned int, vcl_vector<unsigned int>*>::iterator rpf_iterator;
00096   for (rpf_iterator= region_pairs_forward_.begin();
00097        rpf_iterator!=region_pairs_forward_.end(); rpf_iterator++)
00098   {
00099     vcl_cout << (*rpf_iterator).first << " == "
00100              << (*rpf_iterator).second << vcl_endl;
00101   }
00102   vcl_cout << vcl_endl;
00103 }
00104 
00105 //Print the contents of the reverse equivalence index
00106 void gevd_edgel_regions::print_reverse_region_equivalence()
00107 {
00108   vcl_cout << vcl_endl << "Reverse Label Equivalence:\n"
00109            << "----------------\n";
00110   vcl_map<unsigned int, vcl_vector<unsigned int>*>::iterator rpf_iterator;
00111   for (rpf_iterator= region_pairs_reverse_.begin();
00112        rpf_iterator!=region_pairs_reverse_.end(); rpf_iterator++)
00113     {
00114       vcl_cout << (*rpf_iterator).first << " == "
00115                << (*rpf_iterator).second << vcl_endl;
00116     }
00117   vcl_cout << vcl_endl;
00118 }
00119 
00120 //Print the reduced equivalence relation
00121 void gevd_edgel_regions::print_base_equivalence()
00122 {
00123   vcl_cout << vcl_endl << "Base Label Equivalence:\n"
00124            << "----------------\n";
00125 
00126   for (unsigned int i = min_region_label_; i<max_region_label_; i++)
00127     vcl_cout << i << " == " << this->BaseLabel(i) << vcl_endl;
00128 }
00129 
00130 //Print the fitted intensity data for all faces
00131 void gevd_edgel_regions::print_intensity_data()
00132 {
00133   for (vcl_vector<vtol_intensity_face_sptr>::iterator fit =faces_->begin();
00134        fit != faces_->end(); fit++)
00135     {
00136 #if 0
00137     vtol_intensity_face* f = *fit;
00138       vcl_cout << "IntFaceAt(" << f->Xo() << ' ' << f->Yo() << "):\n";
00139       f->PrintFit();
00140 #endif
00141     }
00142 }
00143 
00144 //--------------------------------------------------------------
00145 //: The region array can be offset from the corner of the ROI.
00146 //    The following two methods transform from the ROI coordinate
00147 //    system to the region label array coordinate system
00148 unsigned int gevd_edgel_regions::X(unsigned int x)
00149 {
00150   return x-xo_;
00151 }
00152 
00153 unsigned int gevd_edgel_regions::Y(unsigned int y)
00154 {
00155   return y-yo_;
00156 }
00157 
00158 //---------------------------------------------------------
00159 //: Casts the float x location of a point to an unsigned-int location
00160 unsigned int gevd_edgel_regions::Xf(float x)
00161 {
00162   unsigned int xu = ((unsigned int)(x));
00163   return xu;
00164 }
00165 
00166 //---------------------------------------------------------
00167 //: Casts the float x location of a point to an unsigned-int location
00168 unsigned int gevd_edgel_regions::Yf(float y)
00169 {
00170   unsigned int yu = ((unsigned int)(y));
00171   return yu;
00172 }
00173 
00174 //----------------------------------------------------------
00175 //: Default constructor
00176 gevd_edgel_regions::gevd_edgel_regions(bool debug)
00177 {
00178   verbose_ = false;
00179   debug_ = debug;
00180 #if 0
00181   if (debug_)
00182     debug_data_ = new topo_debug_data;
00183   else
00184     debug_data_ = 0;
00185 #endif
00186     image_ = NULL;
00187   image_source_ = false;
00188   buf_source_ = false;
00189   buf_ = NULL;
00190   edge_boundary_array_ = NULL;
00191   region_label_array_ = NULL;
00192   xo_=0;
00193   yo_=0;
00194   xend_ = 0;
00195   yend_ = 0;
00196   min_region_label_ = LABEL;
00197   max_region_label_ = LABEL;
00198   faces_ = new vcl_vector<vtol_intensity_face_sptr>;
00199   face_edge_index_ = NULL;
00200   intensity_face_index_ = NULL;
00201   failed_insertions_ = new vcl_vector<vtol_edge_2d_sptr>;
00202   ubuf_ = NULL;
00203   sbuf_ = NULL;
00204 }
00205 
00206 //----------------------------------------------------------
00207 //: Default destructor
00208 gevd_edgel_regions::~gevd_edgel_regions()
00209 {
00210   if (image_) {
00211     image_ = NULL;
00212   }
00213 
00214   unsigned int y;
00215   if (region_label_array_)
00216     for (y=yo_; y<=yend_; y++)
00217       delete [] region_label_array_[Y(y)];
00218   delete [] region_label_array_;
00219 
00220 #if 0
00221   for (region_pairs_reverse_.reset(); region_pairs_reverse_.next();)
00222     delete region_pairs_reverse_.value();
00223 
00224   for (region_pairs_forward_.reset(); region_pairs_forward_.next();)
00225     delete region_pairs_forward_.value();
00226   for (equivalence_set_.reset(); equivalence_set_.next();)
00227     delete equivalence_set_.value();
00228 
00229   for (region_edges_.reset(); region_edges_.next();)
00230   {
00231     region_edges_.value()->UnProtect();
00232   }
00233 
00234    if (edge_boundary_array_)
00235      for (y = yo_; y<=yend_; y++)
00236      {
00237        for (x = xo_; x<=xend_; x++)
00238          if (edge_boundary_array_[Y(y)][X(x)])
00239            edge_boundary_array_[Y(y)][X(x)]->UnProtect();
00240        delete [] edge_boundary_array_[Y(y)];
00241      }
00242    delete [] edge_boundary_array_;
00243 
00244 
00245   for (region_edge_adjacency_.reset(); region_edge_adjacency_.next();)
00246     delete region_edge_adjacency_.value();
00247 
00248   for (faces_->reset(); faces_->next();)
00249     faces_->value()->UnProtect();
00250   delete faces_;
00251 
00252   if (intensity_face_index_)
00253   {
00254     for (unsigned int i = 0; i<max_region_label_; i++)
00255       if (intensity_face_index_[i])
00256         intensity_face_index_[i]= NULL;
00257     delete [] intensity_face_index_;
00258   }
00259 #endif
00260 
00261 
00262   if (face_edge_index_)
00263     {
00264       for (unsigned int i = 0; i<max_region_label_; i++)
00265         delete face_edge_index_[i];
00266       delete [] face_edge_index_;
00267     }
00268   delete failed_insertions_;
00269   delete [] ubuf_;
00270   delete [] sbuf_;
00271 }
00272 
00273 bool gevd_edgel_regions::compute_edgel_regions(gevd_bufferxy* buf,
00274                                                vcl_vector<vtol_edge_2d_sptr>& sgrp,
00275                                                vcl_vector<vtol_intensity_face_sptr>& faces)
00276 {
00277   buf_ = buf;
00278   image_= NULL;
00279   buf_source_=true;
00280   image_source_=false;
00281   return compute_edgel_regions(sgrp, faces);
00282 }
00283 
00284 //-----------------------------------------------------------------
00285 //: The key process loop.
00286 //  Carries out the steps:
00287 //   1) Connected components 2)Edge-label assignment 3)Collect region
00288 //   boundaries 4) Construct vtol_intensity_faces 5)Calculate intensity fit
00289 bool
00290 gevd_edgel_regions::compute_edgel_regions(vil1_image* image,
00291                                           vcl_vector<vtol_edge_2d_sptr>& sgrp,
00292                                           vcl_vector<vtol_intensity_face_sptr>& faces)
00293 {
00294   image_ = image;
00295   buf_ = NULL;
00296   image_source_=true;
00297   buf_source_ = false;
00298   return compute_edgel_regions(sgrp, faces);
00299 }
00300 
00301 bool gevd_edgel_regions::compute_edgel_regions(vcl_vector<vtol_edge_2d_sptr>& sgrp,
00302                                                vcl_vector<vtol_intensity_face_sptr>& faces)
00303 {
00304 //    corrupt_edges_.clear();
00305 //    corrupt_vertices_.clear();
00306 #if 0
00307   if (debug_data_)
00308   {
00309     debug_data_->clear();
00310     if (buf_source_)
00311       debug_data_->set_buf(buf_);
00312   }
00313 #endif
00314   vul_timer t;
00315   if (!sgrp.size())
00316     return false;
00317 
00318   //Set up the region label array with edge boundaries
00319   this->InitRegionArray(sgrp);
00320   if (verbose_)
00321     this->print_region_array();
00322   //Propagate connected components
00323   unsigned int y, x;
00324   for (y=yo_; y<yend_; y++)
00325     for (x=xo_; x<xend_; x++)
00326       this->UpdateConnectedNeighborhood(X(x), Y(y));
00327   if (verbose_)
00328     this->print_region_array();
00329   //Resolve region label equivalence
00330   this->GrowEquivalenceClasses();
00331   this->PropagateEquivalence();
00332   if (verbose_)
00333     this->print_base_equivalence();
00334   this->ApplyRegionEquivalence();
00335   if (verbose_)
00336     this->print_region_array();
00337 
00338   //Associate Edge(s) with region labels
00339   for (y=yo_; y<yend_; y++)
00340     for (x=xo_; x<xend_; x++)
00341       this->AssignEdgeLabels(X(x), Y(y));
00342 
00343   //Collect Edge(s) bounding each region
00344   this->CollectEdges();
00345   vcl_cout << "Propagate Regions and Collect Edges("
00346            << max_region_label_-min_region_label_ << ") in "
00347            << t.real() << " msecs.\n";
00348 
00349   //Collect Face-Edge associations
00350   this->CollectFaceEdges();
00351 
00352   //Construct vtol_intensity_faces
00353   this->ConstructFaces();
00354   if (!faces_||!faces_->size())
00355     return false;
00356 
00357   //Collect intensity data for each region
00358   this->InsertFaceData();
00359 
00360   if (verbose_)
00361     this->print_intensity_data();
00362   //Output the result
00363   faces.clear();
00364   for (vcl_vector<vtol_intensity_face_sptr>::iterator fit = faces_->begin();
00365        fit != faces_->end(); fit++)
00366   {
00367     faces.push_back(*fit);
00368     //        faces_->value()->Protect(); //This caused a big leak
00369   }
00370   vcl_cout << "Compute Edgel Regions Total(" << sgrp.size() << ") in "
00371            << t.real() << " msecs.\n";
00372   return true;
00373 }
00374 
00375 
00376 //----------------------------------------------------------
00377 //: assign equivalence of region label b to region label a
00378 //
00379 bool gevd_edgel_regions::InsertRegionEquivalence(unsigned int label_b,
00380                                                  unsigned int label_a)
00381 {
00382   bool result = true;
00383   result = result && this->add_to_forward(label_b, label_a);
00384   result = result && this->add_to_reverse(label_a, label_b);
00385   return result;
00386 }
00387 
00388 //--------------------------------------------------------------
00389 //: Get the most basic label equivalent to a given label.
00390 //    If the label_map_ is not defined, this function uses the
00391 //    forward label hash table.  Otherwise 0 is returned.
00392 unsigned int gevd_edgel_regions::BaseLabel(unsigned int label)
00393 {
00394   vcl_map<unsigned int, unsigned int >::iterator lmtest;
00395   lmtest = label_map_.find(label);
00396   if ( lmtest != label_map_.end() )
00397     return lmtest->second;
00398   else
00399     return 0;
00400 }
00401 
00402 //------------------------------------------------------------
00403 //:
00404 //  Paint the edgels into the region label array and then
00405 //    output an image where the value is 255 if the pixel is an
00406 //    edge, 0 otherwise
00407 vil1_image* gevd_edgel_regions::GetEdgeImage(vcl_vector<vtol_edge_2d_sptr>& sg)
00408 {
00409   if (!this->InitRegionArray(sg)) return NULL;
00410   int sizex = this->GetXSize(), sizey = this->GetYSize();
00411   unsigned char no_edge = 0, edge = 255;
00412 #if 0
00413   ImageTemplate temp(sizex, sizey, 8, 32, 32);
00414   MemoryImage* image = new MemoryImage(&temp);
00415   for (int y = 0; y<sizey; y++)
00416     for (int x = 0; x<sizex; x++)
00417       if (region_label_array_[y][x] == EDGE)
00418         image->PutPixel(&edge, x, y);
00419       else
00420         image->PutPixel(&no_edge, x, y);
00421 #endif
00422   vil1_memory_image_of<vxl_byte> * image = new vil1_memory_image_of<vxl_byte>(sizex,sizey);
00423 
00424   for (int y = 0; y<sizey; y++)
00425     for (int x = 0; x<sizex; x++)
00426       if (region_label_array_[y][x] == EDGE)
00427         (*image)[y][x] = edge;
00428       else
00429         (*image)[y][x] = no_edge;
00430   return image;
00431 }
00432 
00433 //-----------------------------------------------------------
00434 //: Populate the label_map_ to reflect the equivalences between labels.
00435 //
00436 void gevd_edgel_regions::PropagateEquivalence()
00437 {
00438   vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator  esi;
00439 
00440   for (esi = equivalence_set_.begin(); esi != equivalence_set_.end(); esi++)
00441   {
00442     unsigned int base = esi->first;
00443     vcl_vector<unsigned int>* labels = esi->second;
00444     if (!labels) continue;
00445     int len = labels->size();
00446     if (!len) continue;
00447     for (int i = 0; i<len; i++)
00448       label_map_[(*labels)[i]] = base;
00449   }
00450   for (unsigned int i = min_region_label_; i<max_region_label_; i++)
00451     if (label_map_.find(i) == label_map_.end())
00452       label_map_[i] = i;
00453 }
00454 
00455 //---------------------------------------------------------------------
00456 //:
00457 //  Find the set of labels equivalent to label from a given hash table
00458 //    and merge into the appropriate equivalence set. cur_label is the
00459 //    equivalence set being formed. label is the table key of equivalences
00460 //    to be merged.
00461 bool gevd_edgel_regions::
00462 merge_equivalence(vcl_map<unsigned int, vcl_vector<unsigned int>* >& tab,
00463                   unsigned int cur_label,
00464                   unsigned int label)
00465 {
00466   vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator hashi;
00467 
00468   hashi = tab.find(label);
00469   if (hashi == tab.end()) {
00470   return false;
00471   }
00472   vcl_vector<unsigned int>* labels = hashi->second;
00473 
00474   int len = labels->size();
00475   if (!len) {
00476     return false;
00477   }
00478   vcl_vector<unsigned int>* array;
00479 
00480   hashi = equivalence_set_.find(cur_label);
00481   if ( hashi == equivalence_set_.end())
00482   {
00483     array = new vcl_vector<unsigned int>;
00484     equivalence_set_[cur_label] = array;
00485   }
00486   else
00487   {
00488     array = hashi->second;
00489   }
00490   for (int i = 0; i<len; i++)
00491   {
00492     unsigned int l = (*labels)[i];
00493     bool found = false;
00494     for (unsigned int j=0 ; j < array->size() ; j++)
00495     {
00496       if ((*array)[j] == l) found = true;
00497     }
00498     if (!found)
00499     {
00500       array->push_back(l);
00501     }
00502   }
00503 
00504   return true;
00505 }
00506 
00507 //----------------------------------------------------------------
00508 //: Find the next label not accounted for in the current equivalence set.
00509 //    The set of labels is searched to find a label larger than label, but
00510 //    not in the set, labels.
00511 bool gevd_edgel_regions::get_next_label(vcl_vector<unsigned int>* labels,
00512                                         unsigned int& label)
00513 {
00514   unsigned int tmp = label+1;
00515   if (!labels)
00516     if (tmp<max_region_label_)
00517     {
00518       label = tmp;
00519       return true;
00520     }
00521   for (unsigned int i = tmp; i<max_region_label_; i++)
00522   {
00523     bool found = false;
00524     for ( unsigned int j = 0 ; j < labels->size() ; j++ )
00525     {
00526       if ((*labels)[j] == i)
00527       {
00528         found = true;
00529       }
00530     }
00531     if (!found)
00532     {
00533       label = i;
00534       return true;
00535     }
00536   }
00537   return false;
00538 }
00539 
00540 //----------------------------------------------------------------
00541 //: Form equivalence classes by transitive closure on each label.
00542 //    The idea is to add labels to the set, cur_set, by equivalence until no
00543 //    new equivalence groups can be found.  The current equivalence class,
00544 //    cur_set is repeatedly scanned when new labels are added to pick up
00545 //    new equivalence groups.  Old equivalence table entries are removed
00546 //    as they are used.  When the equivalence class corresponding to cur_lable
00547 //    is completely closed, then a new label not in a previously formed
00548 //    equivalence class is used to seed a new equivalence class.
00549 void gevd_edgel_regions::GrowEquivalenceClasses()
00550 {
00551   if ((max_region_label_-min_region_label_) < 2)
00552     return;
00553   unsigned int cur_label = min_region_label_;
00554   vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator mei;
00555   while (true)
00556     {
00557       bool merging = true;
00558       vcl_vector<unsigned int>* cur_set = NULL;
00559       unsigned int i = cur_label;
00560       int len = 0;
00561       while (merging)
00562       {
00563         int old_len = len;
00564         merging = false;
00565         bool find_forward =
00566           this->merge_equivalence(region_pairs_forward_, cur_label, i);
00567         if (find_forward)
00568           region_pairs_forward_.erase(i);
00569         bool find_reverse =
00570           this->merge_equivalence(region_pairs_reverse_, cur_label, i);
00571         if (find_reverse)
00572           region_pairs_reverse_.erase(i);
00573         mei = equivalence_set_.find(cur_label);
00574         if (mei == equivalence_set_.end()) continue;
00575         cur_set = equivalence_set_[cur_label];
00576         if (!cur_set) continue;
00577         len = cur_set->size();
00578         if (!len) continue;
00579         if (len > old_len)
00580         {
00581           i = cur_label;
00582           vcl_sort(cur_set->begin(), cur_set->end(), &increasing_compare);
00583 #if 0
00584           cur_set->sort(increasing_compare);
00585           //-tpk- need to convert
00586 #endif
00587         }
00588 
00589         for (int j = 0; j<len&&!merging; j++)
00590           if ((*cur_set)[j]>i)
00591           {
00592             i = (*cur_set)[j];
00593             merging = true;
00594           }
00595       }
00596       if (!get_next_label(cur_set, cur_label)) return;
00597     }
00598 }
00599 
00600 //------------------------------------------------------------
00601 //: Check if the SpatialGroup contains Edge(s)
00602 //
00603 bool gevd_edgel_regions::GroupContainsEdges(vcl_vector<vtol_edge_2d_sptr>& /*sg*/)
00604 {
00605   vcl_cerr << "gevd_edgel_regions::GroupContainsEdges() not yet implemented\n";
00606 #if 0
00607   vcl_string type(sg.GetSpatialGroupName());
00608   return type == vcl_string("EdgelGroup") ||
00609          type == vcl_string("FittedEdgeGroup");
00610 #endif
00611   return true; // TODO
00612 }
00613 
00614 //: Advance along a line and generate contiguous pixels on the line.
00615 //  This function assures that the spatial digitization of the Edge(s)
00616 //  produces completely connected boundaries.
00617 static bool line_gen(float xs, float ys, float xe, float ye,
00618                      unsigned int& x, unsigned int& y)
00619 {
00620   assert(xs > 0.0f); assert(ys > 0.0f);
00621   const float pix_edge = 1.0f; //We are working at scale = 1.0
00622   static float xi, yi;
00623   static bool init = true;
00624   static bool done = false;
00625   if (init)
00626     {
00627       xi = xs;
00628       yi = ys;
00629       x = (unsigned int)(xi/pix_edge);
00630       y = (unsigned int)(yi/pix_edge);
00631       init = false;
00632       return true;
00633     }
00634   if (done) return false;
00635   float dx = xe-xs;
00636   float dy = ye-ys;
00637   float mag = vcl_sqrt(dx*dx + dy*dy);
00638   if (mag<pix_edge)//Can't reach the next pixel under any circumstances
00639     {             //so just output the target, xe, ye.
00640       x = (unsigned int)xe; y = (unsigned int)ye;
00641       done = true;
00642       return true;
00643     }
00644   float delta = (0.5f*pix_edge)/mag; //move in 1/2 pixel increments
00645   //Previous pixel location
00646   int xp = int(xi/pix_edge);
00647   int yp = int(yi/pix_edge);
00648   //Increment along the line until the motion is greater than one pixel
00649   for (int i = 0; i<3; i++)
00650     {
00651       xi += dx*delta;
00652       yi += dy*delta;
00653       //Check for end of segment, make sure we emit the end of the segment
00654       if ((xe>=xs&&xi>xe)||(xe<=xs&&xi<xe)||(ye>=ys&&yi>ye)||(ye<=ys&&yi<ye))
00655         {
00656           x = (unsigned int)xe; y = (unsigned int)ye;
00657           done = true;
00658           return true;
00659         }
00660       //Check if we have advanced by more than .5 pixels
00661       x = (unsigned int)(xi/pix_edge);
00662       y = (unsigned int)(yi/pix_edge);
00663       if (vcl_abs(int(x)-xp)>(.5*pix_edge)||vcl_abs(int(y)-yp)>(.5*pix_edge))
00664         return true;
00665     }
00666   vcl_cout << "in gevd_edgel_regions line_gen: - shouldn't happen\n";
00667   return false;
00668 }
00669 
00670 //----------------------------------------------------------
00671 //: A utility for inserting an edgel into the region_label_array_.
00672 //    An edgel and a previous edgel in the chain are used to interpolate
00673 //    intermediate edgels to take account of pixel quantization
00674 bool gevd_edgel_regions::insert_edgel(float pre_x, float pre_y,
00675                                       float xedgel, float yedgel, gevd_region_edge* re)
00676 {
00677   unsigned int xinterp, yinterp;
00678   bool edge_insert = false;
00679   while (line_gen(pre_x, pre_y, xedgel, yedgel, xinterp, yinterp))
00680     {
00681       if (out_of_bounds(X(xinterp), Y(yinterp)))
00682         {
00683           vcl_cout << "In gevd_edgel_regions::insert_edgel - out of bounds "
00684                    << "at (" << xinterp << ' ' << yinterp << ")\n";
00685           continue;
00686         }
00687 
00688       region_label_array_[Y(yinterp)][X(xinterp)] = EDGE;
00689 
00690       if (!re) continue;
00691       gevd_region_edge* old_re = edge_boundary_array_[Y(yinterp)][X(xinterp)];
00692       if (old_re&&old_re->get_edge())
00693         {
00694         //        old_re->UnProtect();
00695           edge_boundary_array_[Y(yinterp)][X(xinterp)] = re;
00696           //      re->Protect();
00697           edge_insert = true;
00698         }
00699       if (!old_re)
00700         {
00701           edge_boundary_array_[Y(yinterp)][X(xinterp)] = re;
00702           //      re->Protect();
00703           edge_insert = true;
00704         }
00705     }
00706   return edge_insert;
00707 }
00708 
00709 int gevd_edgel_regions::bytes_per_pix()
00710 {
00711   int bypp = 1;
00712   if (image_source_)
00713     bypp = (image_->components() / image_->bits_per_component());
00714 
00715   if (buf_source_)
00716     bypp = buf_->GetBytesPixel();
00717   return bypp;
00718 }
00719 
00720 //-----------------------------------------------------------
00721 //: Initialize the region label array.
00722 //  There are three types of region label symbols:
00723 //  1) UNLABELED - no label has yet been assigned,
00724 //  2) EDGE, the existence of an edgel boundary pixel.
00725 //  3) An unsigned integer which represents an existing region label.
00726 
00727 bool gevd_edgel_regions::InitRegionArray(vcl_vector< vtol_edge_2d_sptr>& sg)
00728 {
00729   if (!this->GroupContainsEdges(sg))
00730     return false;
00731 
00732   double xmin;
00733   double ymin;
00734   double xmax;
00735   double ymax;
00736   vsol_box_2d_sptr b;
00737 
00738   vcl_vector<vtol_edge_2d_sptr>::iterator i = sg.begin();
00739   assert( i != sg.end() );
00740   b=(*i)->get_bounding_box();
00741   xmin=b->get_min_x();
00742   ymin=b->get_min_y();
00743   xmax=b->get_max_x();
00744   ymax=b->get_max_y();
00745   for (++i; i!=sg.end(); ++i)
00746     {
00747       b=(*i)->get_bounding_box();
00748       if (b->get_min_x()<xmin)
00749         xmin=b->get_min_x();
00750       if (b->get_min_y()<ymin)
00751         ymin=b->get_min_y();
00752       if (b->get_max_x()>xmax)
00753         xmax=b->get_max_x();
00754       if (b->get_max_y()>ymax)
00755         ymax=b->get_max_y();
00756     }
00757 
00758   //Get the size of the arrays
00759   xo_ = (unsigned int)xmin;
00760   yo_ = (unsigned int)ymin;
00761 
00762   xend_ = (unsigned int)xmax;
00763   yend_ = (unsigned int)ymax;
00764 
00765   unsigned int sizex = xend_ - xo_ + 1;
00766   unsigned int sizey = yend_ - yo_ + 1;
00767   //Construct the arrays
00768   edge_boundary_array_ = new gevd_region_edge**[sizey];
00769   unsigned int y;
00770   for (y = yo_; y<=yend_; y++)
00771     edge_boundary_array_[Y(y)] = new gevd_region_edge*[sizex];
00772 
00773   region_label_array_ = new unsigned int*[sizey];
00774   for (y = yo_; y<=yend_; y++)
00775     region_label_array_[Y(y)] = new unsigned int[sizex];
00776 
00777   switch (this->bytes_per_pix())
00778   {
00779    case 1:     // Grey scale image with one byte per pixel
00780     ubuf_ = new unsigned char[sizex];
00781     break;
00782    case 2:     // Grey scale image with an unsigned short per pixel
00783      sbuf_ = new unsigned short[sizex];
00784      break;
00785    default:
00786     vcl_cout<<"In vtol_intensity_face::get_intensity(): bytes/pixel not 1 or 2\n";
00787   }
00788 
00789   //Initialize the arrays
00790   unsigned int x;
00791   if (ubuf_)
00792     for (x = xo_; x<=xend_; x++)
00793       ubuf_[X(x)] = 0;
00794 
00795   if (sbuf_)
00796     for (x = xo_; x<=xend_; x++)
00797       sbuf_[X(x)] = 0;
00798 
00799   for (y = yo_; y<=yend_; y++)
00800     for (x = xo_; x<=xend_; x++)
00801       {
00802         region_label_array_[Y(y)][X(x)] = UNLABELED;
00803         edge_boundary_array_[Y(y)][X(x)] = NULL;
00804       }
00805   //Insert edgels into arrays.
00806 
00807   int counter=0;
00808   for (vcl_vector<vtol_edge_2d_sptr >::iterator sgit = sg.begin();
00809        sgit != sg.end(); sgit++)
00810     {
00811       vtol_edge_2d_sptr e = (*sgit);
00812       if (!e)
00813         continue;
00814       e->set_id(counter++);
00815       vdgl_digital_curve* dc = e->curve()->cast_to_vdgl_digital_curve();
00816       if (!dc)
00817         continue;
00818       //The gevd_region_edge enables the link between a region label and
00819       //an Edge from the input segmentation
00820       gevd_region_edge* re = new gevd_region_edge(e);
00821       region_edges_[e->get_id()] = re;
00822       //      e->Protect(); re->Protect();
00823       //      float * ex = dc->GetX();
00824       //      float * ey = dc->GetY();
00825       vdgl_edgel_chain_sptr xy= dc->get_interpolator()->get_edgel_chain();
00826       int n_edgels = xy->size();
00827 
00828       //Insert the vertices at the ends of the edge
00829       //If there is a gap between the vertex locations and the
00830       //nearest edgels, the insert_edgel function will generate
00831       //edge insertions to prevent any gaps in the region boundary
00832       //There shouldn't be DigitalCurve(s) with this defect but it
00833       //does seem to occur.
00834       gevd_region_edge* vre = new gevd_region_edge(NULL);
00835       float pex1, pey1, pex2, pey2;
00836       if (n_edgels>0)
00837         {
00838           pex1 = float((*xy)[0].x()); pex2 = float((*xy)[n_edgels-1].x());
00839           pey1 = float((*xy)[0].y()); pey2 = float((*xy)[n_edgels-1].y());
00840           this->insert_edgel(pex1, pey1,
00841                              float(e->v1()->cast_to_vertex_2d()->x()),
00842                              float(e->v1()->cast_to_vertex_2d()->y()),
00843                              vre);
00844           this->insert_edgel(pex2, pey2,
00845                              float(e->v2()->cast_to_vertex_2d()->x()),
00846                              float(e->v2()->cast_to_vertex_2d()->y()),
00847                              vre);
00848         }
00849       else
00850         {
00851           pex1 = float(e->v1()->cast_to_vertex_2d()->x());
00852           pey1 = float(e->v1()->cast_to_vertex_2d()->y());
00853           pex2 = float(e->v2()->cast_to_vertex_2d()->x());
00854           pey2 = float(e->v2()->cast_to_vertex_2d()->y());
00855           this->insert_edgel(pex1, pey1, pex1, pey1, vre);
00856           this->insert_edgel(pex1, pey1, pex2, pey2, vre);
00857         }
00858       //Insert the edgels between the vertices
00859       //An edgel cannot be inserted on top of an existing vertex
00860       //insertion.  A vertex is distinguished by having a NULL Edge.
00861       //That is, for vertices it is ambiguous what Edge instance
00862       //exists at that location. Edge insertion fails if no edgels
00863       //of the Edge can be sucessfully inserted.
00864       bool edge_insert = false;
00865       for (int k =0; k < n_edgels; k++)
00866         {
00867           bool inserted = this->insert_edgel(pex1, pey1, float((*xy)[k].x()), float((*xy)[k].y()), re);
00868           edge_insert = edge_insert || inserted;
00869           pex1 = float((*xy)[k].x());
00870           pey1 = float((*xy)[k].y());
00871         }
00872       if (!edge_insert)
00873         {
00874           vcl_cout << "Edge Insert Failed for (" << e->v1() << ' '
00875                    << e->v2() << ")N: "<< n_edgels << vcl_endl;
00876           failed_insertions_->push_back(e);
00877         }
00878     }
00879   return true;
00880 }
00881 
00882 //---------------------------------------------------------------
00883 //: Get code for a given label.
00884 //
00885 unsigned char gevd_edgel_regions::label_code(unsigned int label)
00886 {
00887   unsigned char result;
00888   if (label<min_region_label_)
00889     result = label;
00890   else
00891     result = LABEL;
00892   return result;
00893 }
00894 
00895 //----------------------------------------------------------------
00896 //: Add a new pair to the forward equivalence list.
00897 //    That is, a ==> b. Note that there can be multiple equivalences which are
00898 //    stored in a vcl_vector
00899 bool gevd_edgel_regions::add_to_forward(unsigned int key, unsigned int value)
00900 {
00901   bool result = true;
00902   vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator rpfi;
00903   rpfi = region_pairs_forward_.find(key);
00904 
00905   if (rpfi !=region_pairs_forward_.end())
00906     {
00907     vcl_vector<unsigned int> * vec = region_pairs_forward_[key];
00908     bool found = false;
00909     for (unsigned int i =0 ; i < vec->size() ; i++)
00910       {
00911       if ((*vec)[i] == value)
00912         found = true;
00913       }
00914     if (!found)
00915       {
00916       vec->push_back(value);
00917       }
00918     }
00919   else
00920     {
00921       vcl_vector<unsigned int>* larray = new vcl_vector<unsigned int>;
00922       larray->push_back(value);
00923        region_pairs_forward_[key]=larray;
00924     }
00925   return result;
00926 }
00927 
00928 //----------------------------------------------------------------
00929 //: Add a new pair to the reverse equivalence list.
00930 //    That is, b==>a. Note that there can be multiple equivalences which are
00931 //    stored in a vcl_vector
00932 //
00933 bool gevd_edgel_regions::add_to_reverse(unsigned int key, unsigned int value)
00934 {
00935   bool result = true;
00936   vcl_map<unsigned int, vcl_vector<unsigned int>* >::iterator rpfi;
00937   rpfi = region_pairs_reverse_.find(key);
00938 
00939   if (rpfi !=region_pairs_reverse_.end())
00940     {
00941     vcl_vector<unsigned int> * vec = region_pairs_reverse_[key];
00942     bool found = false;
00943     for (unsigned int i =0 ; i < vec->size() ; i++)
00944       {
00945       if ((*vec)[i] == value)
00946         found = true;
00947       }
00948     if (!found)
00949       {
00950       vec->push_back(value);
00951       }
00952     }
00953   else
00954     {
00955       vcl_vector<unsigned int>* larray = new vcl_vector<unsigned int>;
00956       larray->push_back(value);
00957        region_pairs_reverse_[key]=larray;
00958     }
00959   return result;
00960 }
00961 
00962 //-------------------------------------------------------------------
00963 //: Encode a 2x2 neighbor hood with the state of the region array for a given location.
00964 //    The Neighborhood    The states are:
00965 //         ul ur          UNLABELED, EDGE, LABEL
00966 //         ll lr              0       1      2
00967 //    The encoding maps the 2x2 pattern to an unsigned char.  The layout
00968 //    of the uchar is:  [ul|ur|ll|lr] with 2 bits for the state of each
00969 //    position.
00970 unsigned char
00971 gevd_edgel_regions::EncodeNeighborhood(unsigned int ul, unsigned int ur,
00972                                        unsigned int ll, unsigned int lr)
00973 {
00974   unsigned char nhood = 0;
00975 
00976   unsigned char nul = label_code(ul);
00977   nul = nul<<6;
00978   nhood |= nul;
00979 
00980   unsigned char nur = label_code(ur);
00981   nur = nur<<4;
00982   nhood |= nur;
00983 
00984   unsigned char nll = label_code(ll);
00985   nll = nll << 2;
00986   nhood |= nll;
00987 
00988   unsigned char nlr = label_code(lr);
00989   nhood |= nlr;
00990 
00991   return nhood;
00992 }
00993 
00994 //----------------------------------------------------------------------
00995 // --This is the fundamental assignment of label equivalence
00996 //
00997 void gevd_edgel_regions::insert_equivalence(unsigned int ll, unsigned int ur, unsigned int& lr)
00998 {
00999   if (ll!=ur)//Is a=b?
01000     {//No. We want the smallest label to be the equivalence base
01001       //Also we don't want to loose earlier equivalences
01002       unsigned int smaller_label, larger_label;
01003       //Get the ordering right
01004       if (ll>ur)
01005         {smaller_label = ur; larger_label = ll;}
01006       else
01007         {smaller_label = ll; larger_label = ur;}
01008       this->add_to_forward(larger_label, smaller_label);
01009       this->add_to_reverse(smaller_label, larger_label);
01010       lr = smaller_label;
01011     }
01012   else //yes, a=b the simple case
01013     lr = ur;
01014 }
01015 
01016 //-------------------------------------------------------------------
01017 //: Propagate connected components.
01018 //    Uses an unsigned char encoding
01019 //    a 2x2 neighborhood to propagate region labels. For example:
01020 //    aa ->   aa
01021 //    xx ->   aa
01022 //    Here the lower two labels are set to the upper label.
01023 //    This method operates directly on the region_label_array_.
01024 //
01025 //    Note that the 2x2 neighborhood is encoded as uchar = [ul|ur|ll|lr]
01026 //                                                          2  2  2  2  bits
01027 void gevd_edgel_regions::UpdateConnectedNeighborhood(unsigned int x, unsigned int y)
01028 {
01029   unsigned int ul = region_label_array_[y][x];
01030   unsigned int ur = region_label_array_[y][x+1];
01031   unsigned int& ll = region_label_array_[y+1][x];
01032   unsigned int& lr = region_label_array_[y+1][x+1];
01033 
01034   unsigned char nhood = this->EncodeNeighborhood(ul, ur, ll, lr);
01035   switch(int(nhood))
01036   {
01037     case 0:
01038       //xx xx
01039       //xx xx
01040       return;
01041     case 1:
01042       //xx xx
01043       //xe xe
01044       return;
01045     case 5:
01046       //xx xx
01047       //ee ee
01048       return;
01049 
01050     case 17:
01051       //xe xe
01052       //xe xe
01053       return;
01054 
01055     case 20:
01056       //xe xe
01057       //ex ea
01058       lr = max_region_label_++;
01059       return;
01060 
01061     case 21:
01062       //xe xe
01063       //ee ee
01064       return;
01065 
01066     case 22:
01067       //xe xe
01068       //ea ea
01069       return;
01070 
01071     case 68:
01072       //ex ex
01073       //ex ex
01074       return;
01075 
01076     case 72:
01077       //ex ex
01078       //ax ax
01079       return;
01080 
01081     case 133:
01082       //ax aa
01083       //ee ee
01084       return;
01085 
01086     case 136:
01087       //ax ax
01088       //ax ax
01089       return;
01090 
01091     case 160:
01092       //aa aa
01093       //xx aa
01094       ll = ul;
01095       lr = ul;
01096       return;
01097 
01098     case 161:
01099       //aa aa
01100       //xe ae
01101       ll = ul;
01102       return;
01103 
01104     case 168:
01105       //aa aa
01106       //ax aa
01107       insert_equivalence(ll, ur, lr);
01108       return;
01109 
01110     case 169:
01111       //aa aa
01112       //ae ae
01113       return;
01114 
01115     case 164:
01116       //aa aa
01117       //ex ea
01118       lr = ul;
01119       return;
01120 
01121     case 165:
01122       //aa aa
01123       //ee ee
01124       return;
01125 
01126     case 144:
01127       //ae ae
01128       //xx aa
01129       ll = ul;
01130       lr = ul;
01131       return;
01132 
01133     case 145:
01134       //ae ae
01135       //xe ae
01136       ll = ul;
01137       return;
01138 
01139     case 152:
01140       //ae ae
01141       //ax aa
01142       lr = ul;
01143       return;
01144 
01145     case 153:
01146       //ae ae
01147       //ae ae
01148       return;
01149 
01150     case 148:
01151       //ae ae
01152       //ex eb
01153       lr = max_region_label_++;
01154       return;
01155 
01156     case 149:
01157       //ae ae
01158       //ee ee
01159       return;
01160 
01161     case 96:
01162       //ea ea
01163       //xx aa
01164       ll = ur;
01165       lr = ur;
01166       return;
01167 
01168     case 97:
01169       //ea ea
01170       //xe be
01171       ll = max_region_label_++;
01172       return;
01173 
01174     case 104:
01175       //ea ea
01176       //bx aa
01177       insert_equivalence(ll, ur, lr);
01178       return;
01179 
01180     case 105:
01181       //ea ea
01182       //ae ae
01183       return;
01184 
01185     case 100:
01186       //ea ea
01187       //ex ea
01188       lr = ur;
01189       return;
01190 
01191     case 101:
01192       //ea ea
01193       //ee ee
01194       return<