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

gevd_clean_edgels.cxx

Go to the documentation of this file.
00001 // This is gel/gevd/gevd_clean_edgels.cxx
00002 #include "gevd_clean_edgels.h"
00003 //:
00004 // \file
00005 
00006 #include <vcl_iostream.h>
00007 #include <vcl_vector.h>
00008 #include <vcl_algorithm.h> // for vcl_find()
00009 #include <vul/vul_timer.h>
00010 #include <vsol/vsol_point_2d.h>
00011 #include <vdgl/vdgl_digital_curve_sptr.h>
00012 #include <vdgl/vdgl_digital_curve.h>
00013 #include <vdgl/vdgl_edgel_chain_sptr.h>
00014 #include <vdgl/vdgl_edgel_chain.h>
00015 #include <vdgl/vdgl_interpolator_sptr.h>
00016 #include <vdgl/vdgl_interpolator.h>
00017 #include <vdgl/vdgl_interpolator_linear.h>
00018 #include <vtol/vtol_edge.h>
00019 #include <vtol/vtol_edge_2d.h>
00020 
00021 static bool verbose = false;
00022 
00023 static bool near_equal(vdgl_digital_curve_sptr /*dc1*/, vdgl_digital_curve_sptr /*dc2*/, float /*tolerance*/)
00024 {
00025   vcl_cerr << __FILE__ << ": near_equal(dc1,dc2) not yet implemented\n";
00026   return false; // TODO
00027 #if 0
00028   if (!(dc1&&dc2))
00029     return false;
00030   bool similar=true;
00031   double n1 = dc1->length(), n2 = dc2->length(), ns;
00032   //Curves should be similar in length
00033   if (vcl_fabs(n1-n2)>tolerance)
00034     return false;
00035 
00036   //Get the shortest curve to probe with
00037   vdgl_digital_curve_sptr dcs = NULL, dcl = NULL; //s for short, l for long
00038   if (n1>n2) { dcs = dc2; dcl = dc1; ns = n2; }
00039   else       { dcs = dc1; dcl = dc2; ns = n1; }
00040 
00041   //Scan the sort curve and get the distance from each edgel
00042   //to the longer curve.
00043   for (int i = 0; i<ns; i++)
00044   {
00045     vnl_vector<float> ps(X[i], Y[i], 0.0);
00046     float d = dcl->DistanceFrom(ps);
00047     if (d>tolerance) // A single distance violation means they aren't similar
00048     { similar = false; break; }
00049   }
00050   return similar;
00051 #endif
00052 }
00053 
00054 
00055 void gevd_clean_edgels::print_protection()
00056 {
00057 #ifdef DEBUG
00058   vcl_cout << "Protection Values: ";
00059   for (EdgelGroup::iterator egit = out_edgels_->begin();
00060        egit != out_edgels_->end(); ++egit)
00061     vcl_cout << (*egit)->GetProtection() << ' ';
00062   vcl_cout << vcl_endl << vcl_endl;
00063 #endif
00064 }
00065 
00066 
00067 //:Default Constructor
00068 gevd_clean_edgels::gevd_clean_edgels()
00069 {
00070   out_edgels_ = NULL;
00071 }
00072 
00073 
00074 //:Default Destructor
00075 gevd_clean_edgels::~gevd_clean_edgels()
00076 {
00077 }
00078 
00079 
00080 //: The main process method.  The input edgel group is filtered to remove bridges and short edges.
00081 void gevd_clean_edgels::DoCleanEdgelChains(vcl_vector<vtol_edge_2d_sptr>& in_edgels,
00082                                            vcl_vector<vtol_edge_2d_sptr>& out_edgels, int steps)
00083 {
00084   vul_timer t;
00085   out_edgels_= &out_edgels;
00086   out_edgels_->clear();
00087   //Copy the input edges to the output
00088   for (vcl_vector<vtol_edge_2d_sptr>::iterator egit = in_edgels.begin();
00089        egit != in_edgels.end(); ++egit)
00090     out_edgels_->push_back(*egit);
00091   if (steps > 0)
00092     this->JumpGaps();
00093   if (steps > 1)
00094     this->DeleteShortEdges();
00095   if (steps > 2)
00096     this->FixDefficientEdgels();
00097   if (steps > 3)
00098     this->RemoveBridges();
00099   if (steps > 4)
00100     this->RemoveJaggies();
00101   if (steps > 5)
00102     this->RemoveLoops();
00103   vcl_cout << "Total Clean Time(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00104 }
00105 
00106 
00107 //: Merge edges which have all edgels within a given tolerance
00108 //
00109 void gevd_clean_edgels::detect_similar_edges(vcl_vector<vtol_edge_2d_sptr >& common_edges,
00110                                              float tolerance,
00111                                              vcl_vector<vtol_edge_2d_sptr >& deleted_edges)
00112 {
00113   vcl_vector<vtol_edge_2d_sptr > temp;
00114   for (vcl_vector<vtol_edge_2d_sptr >::iterator e1it = common_edges.begin();
00115        e1it != common_edges.end(); ++e1it)
00116   {
00117     vtol_edge_2d_sptr e1 = (*e1it);
00118     vdgl_digital_curve_sptr dc1 = e1->curve()->cast_to_vdgl_digital_curve();
00119     if (!dc1) continue;
00120     vcl_vector<vtol_edge_2d_sptr >::iterator e2it = e1it;
00121     for (e2it++; e2it != common_edges.end(); ++e2it)
00122     {
00123       vtol_edge_2d_sptr e2 = (*e2it);
00124       vdgl_digital_curve_sptr dc2 = e2->curve()->cast_to_vdgl_digital_curve();
00125       if (near_equal(dc1, dc2, tolerance))
00126         temp.push_back(e2);
00127     }
00128   }
00129   for (vcl_vector<vtol_edge_2d_sptr >::iterator eit = temp.begin();
00130        eit != temp.end(); ++eit)
00131   {
00132     vtol_edge_2d_sptr e = (*eit);
00133     // e->unlink_all_inferiors(); // -tpk-
00134     deleted_edges.push_back(e);
00135   }
00136 }
00137 
00138 
00139 //: Find similar edges between v1 and some other vertex v and remove them.
00140 //  In this case, similar means all edgels of the similar edges lie within a given pixel tolerance
00141 //  from each other.
00142 void gevd_clean_edgels::remove_similar_edges(vtol_vertex_2d*& v1, vcl_vector<vtol_edge_2d_sptr >& deleted_edges)
00143 {
00144   float tol = 3.0f;
00145   vcl_vector<vtol_edge_sptr> v1_edges; v1->edges(v1_edges);
00146   vcl_vector<vtol_vertex_2d_sptr> opposite_v1_verts;
00147   //Find all the vertics wes opposite from v1
00148   for (vcl_vector<vtol_edge_sptr>::iterator eit = v1_edges.begin();
00149        eit != v1_edges.end(); ++eit)
00150   {
00151     vtol_vertex_2d_sptr v11 = (*eit)->v1()->cast_to_vertex_2d(),
00152                         v12 = (*eit)->v2()->cast_to_vertex_2d();
00153     if (v11==v1)
00154       {opposite_v1_verts.push_back(v12); continue;}
00155     if (v12==v1)
00156       {opposite_v1_verts.push_back(v11); continue;}
00157     vcl_cout << "In gevd_clean_edgels::remove_similar_edges(..) shouldn't happen\n";
00158   }
00159   //Then get the opposite vertices, v, with more than one edge between v1 and v
00160   //For these edges merge them into a common edge if they are too close
00161   for (vcl_vector<vtol_vertex_2d_sptr>::iterator vit= opposite_v1_verts.begin();
00162        vit != opposite_v1_verts.end(); ++vit)
00163   {
00164     vcl_vector<vtol_edge_2d_sptr > intersection;
00165     this->edge_exists(v1, (*vit), intersection);
00166     if (intersection.size()>1)
00167       this->detect_similar_edges(intersection, tol, deleted_edges);
00168   }
00169 }
00170 
00171 
00172 //: Find if an edge already exists between the given vertices
00173 bool gevd_clean_edgels::edge_exists(vtol_vertex_2d_sptr v1, vtol_vertex_2d_sptr v2, vcl_vector<vtol_edge_2d_sptr >& intersection)
00174 {
00175   bool found = false;
00176   intersection.clear();
00177 
00178   vcl_vector<vtol_edge_sptr> edges; v1->edges(edges);
00179 
00180   for (vcl_vector<vtol_edge_sptr>::iterator eit = edges.begin();
00181        eit != edges.end(); ++eit)
00182   {
00183     vtol_edge_2d* e = (*eit)->cast_to_edge_2d();
00184     if (!e) continue;
00185     if ( (e->v1()->cast_to_vertex_2d() == v1 && e->v2()->cast_to_vertex_2d() == v2) ||
00186          (e->v1()->cast_to_vertex_2d() == v2 && e->v2()->cast_to_vertex_2d() == v1) )
00187     {
00188       intersection.push_back(e);
00189       found = true;
00190     }
00191   }
00192   return found;
00193 }
00194 
00195 
00196 //: Remove edges which are already connected to the given vertex.
00197 void gevd_clean_edgels::remove_connected_edges(vtol_vertex_2d* v, vcl_vector<vtol_edge_2d_sptr >& edges)
00198 {
00199   vcl_vector<vtol_edge_2d_sptr > tmp;
00200   for (vcl_vector<vtol_edge_2d_sptr >::iterator eit = edges.begin();
00201        eit != edges.end(); ++eit)
00202   {
00203     vtol_edge_2d_sptr e = (*eit);
00204     if (e->v1() != v && e->v2() != v)
00205       tmp.push_back(e);
00206   }
00207   edges = tmp;
00208 }
00209 
00210 
00211 //: Find the closest vertex within a given radius on a given edge
00212 //  If one of the edge vertices is within the radius, then choose it.
00213 //  Otherwise return a vertex which lies on, and interior to, the edge.
00214 //  Original compared end vertex distances to radius, now with actual
00215 //  jump span - JLM Sept. 99
00216 bool gevd_clean_edgels::closest_vertex(vtol_edge_2d_sptr e, vsol_point_2d_sptr p, float radius, vtol_vertex_2d_sptr& v)
00217 {
00218   vdgl_digital_curve_sptr dc = e->curve()->cast_to_vdgl_digital_curve();
00219   if (!dc) { v = NULL; return false; }
00220   vsol_point_2d_sptr sp = new vsol_point_2d(*p);
00221   vsol_point_2d_sptr pc = dc->get_interpolator()->closest_point_on_curve( sp );
00222   double span_sq = p->distance(pc);
00223   if (radius < span_sq)
00224     vcl_cerr << __FILE__ << ": closest_vertex(): Warning: ignoring radius="
00225              << radius << " since span=" << span_sq << " is larger\n";
00226 
00227   vtol_vertex_2d_sptr v1 = e->v1()->cast_to_vertex_2d(), v2 = e->v2()->cast_to_vertex_2d();
00228   double d1 = v1->point()->distance(p);
00229   double d2 = v2->point()->distance(p);
00230   if (d1<d2)
00231   {
00232     if (d1<=span_sq)
00233     {
00234       v = v1;
00235       return true;
00236     }
00237   }
00238   else
00239   {
00240   if (d2<=span_sq)
00241   {
00242     v = v2;
00243     return true;
00244   }
00245   }
00246   v = new vtol_vertex_2d(*pc);
00247   return false;
00248 }
00249 
00250 
00251 //: Split an edge at a vertex which is assumed geometrically to lie on the edge.
00252 bool gevd_clean_edgels::split_edge(vtol_edge_2d_sptr e, vtol_vertex_2d_sptr new_v,
00253                                    vtol_edge_2d_sptr & e1, vtol_edge_2d_sptr & e2)
00254 {
00255   if (!e||!new_v)
00256   {
00257     vcl_cout << "In gevd_clean_edgels::split_edge(..) null edge or vertex\n";
00258     return false;
00259   }
00260   vdgl_digital_curve_sptr dc = e->curve()->cast_to_vdgl_digital_curve();
00261   if (!dc)
00262   {
00263     vcl_cout << "In gevd_clean_edgels::split_edge(..) no digital curve\n";
00264     return false;
00265   }
00266 
00267   // Find the proper index
00268   int index = -1;
00269   double min_distance = 10e5;
00270   for (unsigned int i=0; i< dc->get_interpolator()->get_edgel_chain()->size(); ++i)
00271   {
00272     vgl_point_2d<double> curve_point = dc->get_interpolator()->get_edgel_chain()->edgel(i).get_pt();
00273     double d = new_v->point()->distance(vsol_point_2d(curve_point));
00274     if (d < min_distance)
00275     {
00276       index = i;
00277       min_distance = d;
00278     }
00279   }
00280 
00281   vdgl_edgel_chain_sptr cxy= dc->get_interpolator()->get_edgel_chain();
00282 
00283   // 2. Create first subchain up to and including junction pixel.
00284   vtol_edge_2d_sptr edge1 = new vtol_edge_2d();    // create subchains, broken at junction.
00285   vdgl_edgel_chain_sptr ec= new vdgl_edgel_chain;
00286   vdgl_interpolator_sptr it= new vdgl_interpolator_linear( ec);
00287   vdgl_digital_curve_sptr dc1 = new vdgl_digital_curve( it);
00288   edge1->set_curve(*dc1);
00289   vdgl_edgel_chain_sptr cxy1= ec;
00290 
00291   for (int k = 0; k < index; k++)
00292     cxy1->add_edgel( (*cxy)[k] );
00293 
00294   vtol_vertex_2d * v1 = e->v1()->cast_to_vertex_2d();
00295 
00296   edge1->set_v1(v1);            // link both directions v-e
00297   edge1->set_v2(new_v->cast_to_vertex());     // unlink when stronger.UnProtect()
00298 
00299   // Create second subchain from and including junction pixel.
00300   vtol_edge_2d_sptr edge2 = new vtol_edge_2d();    // create second subchain
00301   vdgl_edgel_chain *ec2= new vdgl_edgel_chain;
00302   vdgl_interpolator *it2= new vdgl_interpolator_linear( ec2);
00303   vdgl_digital_curve_sptr dc2= new vdgl_digital_curve( it2);
00304   edge2->set_curve(*dc2);
00305   vdgl_edgel_chain *cxy2= ec2;
00306 
00307   for (unsigned int k = index; k < dc->get_interpolator()->get_edgel_chain()->size(); ++k)
00308     cxy2->add_edgel( cxy->edgel( k ));
00309 
00310   vtol_vertex_sptr v2 = e->v2()->cast_to_vertex();
00311 
00312   edge2->set_v1(new_v->cast_to_vertex());     // link both directions v-e
00313   edge2->set_v2(v2.ptr());            // unlink when stronger.UnProtect()
00314 
00315 
00316 #if 0
00317   if (!dc->Split(*(new_v->GetLocation()), dc1, dc2))
00318   {
00319     e1 = NULL; e2 = NULL;
00320     return false;
00321   }
00322   vtol_vertex_2d_sptr v1 = e->v1()->cast_to_vertex_2d(),
00323                       v2 = e->v2()->cast_to_vertex_2d();
00324   e1 = new vtol_edge_2d(v1, new_v); e2 = new vtol_edge_2d(new_v, v2);
00325   e1->set_curve(dc1) ; e2->set_curve(dc2);
00326 #else
00327   e1 = edge1;
00328   e2 = edge2;
00329 #endif
00330   return true;
00331 }
00332 
00333 
00334 //: Jump gaps by finding the nearest edge to a vertex which is not incident on the vertex.
00335 //  If some point on the digital curve of edge is within a radius of the vertex, then jump across.
00336 //
00337 void gevd_clean_edgels::JumpGaps()
00338 {
00339   vul_timer t;
00340   float radius = 5.0f;
00341   //  float radius = 5.0; Feb 08, 2001 - used in recent DDB exp
00342   //  float radius = 6.0;
00343   //All the vertices of the initial segmentation
00344   vcl_vector<vtol_vertex_2d*> verts;
00345   vcl_vector<vtol_edge_2d_sptr >::iterator eit;
00346   for (eit = out_edgels_->begin(); eit != out_edgels_->end(); ++eit)
00347   {
00348     verts.push_back( (*eit)->v1()->cast_to_vertex_2d() );
00349     verts.push_back( (*eit)->v2()->cast_to_vertex_2d() );
00350   }
00351   //Iterate over the vertices and find nearby edgel chains
00352   for (vcl_vector<vtol_vertex_2d*>::iterator vit = verts.begin();
00353        vit != verts.end(); ++vit)
00354   {
00355     vtol_vertex_2d* v = (*vit);
00356     vsol_point_2d_sptr p = v->point();
00357     //Get the edges within the radius of the vertex
00358     vcl_vector<vtol_edge_2d_sptr > near_edges;
00359 
00360     // out_edgels_->EdgesWithinRadius(*p, radius, near_edges);
00361     // Find edges within the given radius
00362     for (eit = out_edgels_->begin(); eit != out_edgels_->end(); ++eit)
00363     {
00364       vdgl_digital_curve_sptr dc = (*eit)->curve()->cast_to_vdgl_digital_curve();
00365       if (dc && radius > dc->get_interpolator()->distance_curve_to_point(p))
00366         near_edges.push_back( *eit );
00367     }
00368 
00369     if (verbose) vcl_cout << "Found: " << near_edges.size() << " near edges, ";
00370     //Get rid of edges already connected to the vertex
00371 
00372     this->remove_connected_edges(v, near_edges);
00373     if (verbose) vcl_cout << "There were " << near_edges.size() << " after connected removal\n";
00374     //Now iterate over the nearby edges and try to connect
00375     //We assume that the edges all have digital curves
00376           int nnn = 1;
00377     for (eit = near_edges.begin(); eit != near_edges.end() && nnn == 1; ++eit)
00378     {
00379       ///      nnn=0;
00380       vtol_edge_2d_sptr  e = (*eit);
00381       vtol_vertex_2d_sptr new_v = NULL;
00382       //If end_vertex is true, then one of the vertices of e is
00383       //within the given radius
00384       bool end_vertex = this->closest_vertex(e, p, radius, new_v);
00385       if (!new_v) continue; // should always have a new_v
00386       if (!end_vertex)
00387       {
00388         //The new vertex is interior to e,
00389         //so we have to split the edge
00390         vtol_edge_2d_sptr e1=NULL, e2=NULL;
00391         if (verbose) vcl_cout << "Splitting " << e->v1()->cast_to_vertex() << e->v2()->cast_to_vertex() << vcl_endl;
00392         if (!this->split_edge(e, new_v, e1, e2))
00393           continue;
00394         if (verbose) vcl_cout << "It Split, new is: " << *new_v << vcl_endl;
00395         out_edgels_->push_back(e1);
00396         out_edgels_->push_back(e2);
00397         vcl_vector<vtol_edge_2d_sptr >::iterator f;
00398         //e->unlink(); -tpk-
00399         f = vcl_find(out_edgels_->begin(), out_edgels_->end(), e);
00400         if (f != out_edgels_->end())
00401         {
00402           if (verbose) vcl_cout <<"getting rid of old edge\n";
00403           out_edgels_->erase(f);
00404         }
00405       }
00406       //Check if an edge already exists
00407       vcl_vector<vtol_edge_2d_sptr > intersection;//Contains the duplicate edge(s)
00408       if (this->edge_exists(v, new_v, intersection))
00409         {
00410         continue;
00411         }
00412       //Now add the new edge which fills the gap
00413       if (verbose) vcl_cout << "Adding a gap jumping edgel from " << *v << " to " << *new_v << vcl_endl;
00414       vtol_edge_2d_sptr new_edge = new vtol_edge_2d(v, new_v);
00415       // vdgl_digital_curve_sptr dc = new vdgl_digital_curve(v->point(),new_v->point());
00416       vdgl_edgel_chain* new_chain = new vdgl_edgel_chain();
00417       new_chain->add_edgel(vdgl_edgel(v->point()->x(), v->point()->y()));
00418       new_chain->add_edgel(vdgl_edgel(new_v->point()->x(), new_v->point()->y()));
00419       vdgl_digital_curve_sptr dc = new vdgl_digital_curve(new vdgl_interpolator_linear(new_chain));
00420       // dc->set_p0(vsol_point_2d_sptr(new vsol_point_2d(v)));
00421       new_edge->set_curve(*dc);
00422       out_edgels_->push_back(new_edge);
00423     }
00424   }
00425   // delete verts;
00426   vcl_cout << "JumpGaps(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00427 }
00428 
00429 
00430 //: Remove all edges which are shorter than two pixels.
00431 //     That is, e.V1() and e.v2().ptr() are closer than three pixels along both image
00432 //     axes, and no edgel in the vtol_edge_2d is farther than two pixels from vertices.
00433 //     The edge is removed and replaced by a single vertex at the
00434 //     average location.
00435 void gevd_clean_edgels::DeleteShortEdges()
00436 {
00437   int d_remove=2;
00438   int d_close = 1;
00439   vul_timer t;
00440   int N_total=0, N_close=0;
00441   vcl_vector<vtol_edge_2d_sptr > deleted_edges;
00442   int edgelcount = 0;
00443   for (vcl_vector<vtol_edge_2d_sptr >::iterator egit = out_edgels_->begin();
00444        egit != out_edgels_->end(); egit++, ++N_total)
00445   {
00446     if ( (edgelcount % 100) == 0 )
00447       vcl_cout << "Edgels: " << edgelcount << '/' << out_edgels_->size() << vcl_endl;
00448     edgelcount++;
00449     vtol_edge_2d_sptr e = (vtol_edge_2d_sptr )(*egit);
00450     vtol_vertex_2d* v1 = e->v1()->cast_to_vertex_2d();
00451     vtol_vertex_2d* v2 = e->v2()->cast_to_vertex_2d();
00452     double fx1 = v1->x(), fy1 = v1->y();
00453     double fx2 = v2->x(), fy2 = v2->y();
00454     int x1 = int(fx1), y1 = int(fy1);
00455     int x2 = int(fx2), y2 = int(fy2);
00456     int dx = x2-x1; if (dx < 0) dx = -dx; // dx = vcl_abs(x2-x1);
00457     int dy = y2-y1; if (dy < 0) dy = -dy; // dy = vcl_abs(y2-y1);
00458     //First, are the vertices too close?
00459     if (dx<d_remove && dy<d_remove)
00460     {
00461       N_close++;
00462       //If so, then check if all edgels in the EdgelChain are
00463       // too close, i.e, within 2 pixels of both vertices
00464       vdgl_digital_curve_sptr dc = e->curve()->cast_to_vdgl_digital_curve();
00465       vdgl_edgel_chain_sptr chain = dc->get_interpolator()->get_edgel_chain();
00466       int n_edgels = chain->size();
00467       bool all_close = true;
00468       for (int t = 0; (t<n_edgels)&&all_close; t++)
00469       {
00470         int xe = int(chain->edgel(t).x());
00471         int ye = int(chain->edgel(t).y());
00472         dx = xe-x1; if (dx < 0) dx = -dx; // dx = vcl_abs(xe-x1);
00473         dy = ye-y1; if (dy < 0) dy = -dy; // dy = vcl_abs(ye-y1);
00474         bool far_from_v1 = (dx>d_close||dy>d_close);
00475         dx = xe-x2; if (dx < 0) dx = -dx; // dx = vcl_abs(xe-x2);
00476         dy = ye-y2; if (dy < 0) dy = -dy; // dy = vcl_abs(ye-y2);
00477         bool far_from_v2 = (dx>d_close||dy>d_close);
00478         if (far_from_v1&&far_from_v2)
00479           all_close = false;
00480       }
00481 
00482       //They are all too close so, get rid of the edge
00483       if (all_close)
00484       {
00485         // e->unlink_all_inferiors_twoway(e);
00486         // e->unlink_all_inferiors();
00487         // v1->merge_references(v2);
00488         v1->set_x((fx1+fx2)/2);//This could cause missing edgels
00489         v1->set_y((fy1+fy2)/2);
00490         this->remove_similar_edges(v1, deleted_edges);
00491         //We remove e last since it may already
00492         //have been removed by remove_similar_edges
00493         deleted_edges.push_back(e);
00494       }
00495     }
00496   }
00497   for (vcl_vector<vtol_edge_2d_sptr >::iterator eit = deleted_edges.begin();
00498        eit != deleted_edges.end(); ++eit)
00499   {
00500     vcl_vector<vtol_edge_2d_sptr >::iterator f;
00501     // (*eit)->unlink();
00502     f = vcl_find(out_edgels_->begin(), out_edgels_->end(), *eit);
00503     if (f != out_edgels_->end())
00504       out_edgels_->erase( f );
00505   }
00506 
00507   vcl_cout << "Delete Short Edges(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n"
00508            << "Ntotal = " << N_total << "  Nclose =  " << N_close << vcl_endl;
00509 }
00510 
00511 
00512 //: A bridge is an edge or a sequence of edges which is not closed.
00513 //    In this approach, a set of vertices with order one (one incident edge) is
00514 //    found and the associated edges are deleted.  The process is repeated
00515 //    until no more vertices of order one are found.
00516 void gevd_clean_edgels::RemoveBridges()
00517 {
00518   vul_timer t;
00519   bool order_one = true;
00520   vcl_vector<vtol_vertex_2d*> v_one;
00521   while (order_one)
00522   {
00523     //Get the current set of vertices
00524     // vcl_vector<vtol_vertex_2d*>* verts = Vertices(out_edgels_);
00525     vcl_vector<vtol_vertex_2d*> verts;
00526     vcl_vector<vtol_edge_2d_sptr >::iterator eit;
00527     for (eit = out_edgels_->begin(); eit != out_edgels_->end(); ++eit)
00528     {
00529       verts.push_back( (*eit)->v1()->cast_to_vertex_2d() );
00530       verts.push_back( (*eit)->v2()->cast_to_vertex_2d() );
00531     }
00532     v_one.clear();
00533     //Collect all the vertices of order one which are not self-loops.
00534     for (vcl_vector<vtol_vertex_2d*>::iterator vit = verts.begin();
00535          vit != verts.end(); ++vit)
00536     {
00537       vtol_vertex_2d* v = *vit;
00538       vcl_vector<vtol_edge_sptr> edges; v->edges(edges);
00539       if (edges.size()==1)
00540       {
00541         vtol_edge_sptr e = edges[0];
00542         if (e->v1()!=e->v2())
00543           v_one.push_back(v);
00544       }
00545     }
00546     //The main termination condition, i.e., no order one vertices
00547     if (v_one.size()==0)
00548     {
00549       order_one=false;
00550       continue;
00551     }
00552     //Remove the Edge(s) attached to order zero vertices
00553     for (vcl_vector<vtol_vertex_2d*>::iterator v1 = v_one.begin();
00554          v1 != v_one.end(); ++v1)
00555     {
00556       vcl_vector<vtol_edge_sptr> v_edges; (*v1)->edges(v_edges);
00557       int order = v_edges.size();
00558       if (order<1 )
00559       {
00560         //We can leave isolated vertices in v_one
00561         //but they will go away on the next sweep
00562         continue;
00563       }
00564       vtol_edge_sptr ep = v_edges[0];
00565       if (!ep)
00566       {
00567         vcl_cout << "In gevd_clean_edgels::RemoveBridges() - null edge\n";
00568         order_one = false;
00569         continue;
00570       }
00571       vtol_edge_2d_sptr e = ep->cast_to_edge_2d();
00572       if (!e)
00573       {
00574         vcl_cout << "In gevd_clean_edgels::RemoveBridges() - edge is not an edge_2d\n";
00575         order_one = false;
00576         continue;
00577       }
00578       // e->unlink_all_inferiors_twoway(e);
00579       // e->unlink_all_inferiors();
00580       vcl_vector<vtol_edge_2d_sptr >::iterator f;
00581       vcl_cout << "Removing from output edgels: " << e << vcl_endl;
00582       // e->unlink();
00583       f = vcl_find(out_edgels_->begin(), out_edgels_->end(), e);
00584       if (f != out_edgels_->end())
00585       {
00586         out_edgels_->erase(f);
00587       }
00588     }
00589   }
00590   vcl_cout << "Remove Bridges(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00591 }
00592 
00593 
00594 //:
00595 //  Check if the number of edgels is <=2.  If so, replace the
00596 //  vdgl_digital_curve_sptr with one formed from a straight line between the endpoints.
00597 void gevd_clean_edgels::FixDefficientEdgels()
00598 {
00599   vul_timer t;
00600   for (vcl_vector<vtol_edge_2d_sptr >::iterator egit = out_edgels_->begin();
00601        egit!=out_edgels_->end(); ++egit)
00602   {
00603     bool fix_it = false;
00604     vtol_edge_2d_sptr e = (vtol_edge_2d_sptr )(*egit);
00605     vdgl_digital_curve_sptr dc = e->curve()->cast_to_vdgl_digital_curve();
00606     fix_it = fix_it || !dc;
00607     int n_edgels = dc->get_interpolator()->get_edgel_chain()->size();
00608     fix_it = fix_it || n_edgels<=2;
00609     if (fix_it)
00610     {
00611       vtol_vertex_2d_sptr v1 = e->v1()->cast_to_vertex_2d();
00612       vtol_vertex_2d_sptr v2 = e->v2()->cast_to_vertex_2d();
00613       vsol_point_2d_sptr p1 = v1->point();
00614       vsol_point_2d_sptr p2 = v2->point();
00615       // vdgl_digital_curve_sptr dc = new vdgl_digital_curve(p1, p2);
00616       vdgl_edgel_chain_sptr chain = new vdgl_edgel_chain();
00617       // chain->set_p0(p1);
00618       // chain->set_p1(p2);
00619       chain->add_edgel(vdgl_edgel(p1->x(), p1->y()));
00620       chain->add_edgel(vdgl_edgel(p2->x(), p2->y()));
00621       vdgl_digital_curve_sptr dc = new vdgl_digital_curve(new vdgl_interpolator_linear(chain));
00622       e->set_curve(*dc);
00623     }
00624   }
00625   vcl_cout << "Fix Defficient Edgels(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00626 }
00627 
00628 
00629 //:
00630 //    The VD edgedetector produces wild jaggies in the contour
00631 //    from time to time.  This function "smooths' the digital
00632 //    chains by removing sharp adjacent excursions.
00633 void gevd_clean_edgels::RemoveJaggies()
00634 {
00635   vul_timer t;
00636   for (vcl_vector<vtol_edge_2d_sptr >::iterator egit = out_edgels_->begin();
00637        egit!=out_edgels_->end(); ++egit)
00638   {
00639     vtol_edge_2d_sptr e = (vtol_edge_2d_sptr )(*egit);
00640     vtol_vertex_2d_sptr v1 = e->v1()->cast_to_vertex_2d();
00641     vtol_vertex_2d_sptr v2 = e->v2()->cast_to_vertex_2d();
00642     double x1 = v1->x(), y1 = v1->y();
00643     double x2 = v2->x(), y2 = v2->y();
00644     vdgl_digital_curve_sptr dc = e->curve()->cast_to_vdgl_digital_curve();
00645     vdgl_edgel_chain_sptr chain = dc->get_interpolator()->get_edgel_chain();
00646     int n_edgels = chain->size();
00647     int n1 = n_edgels-1;
00648     double xo = chain->edgel(0).x(), yo = chain->edgel(0).y();
00649     // dc->GetX(0), yo = dc->GetY(0);
00650     // float xn = dc->GetX(n1), yn = dc->GetY(n1);
00651     double xn = chain->edgel(n1).x(), yn = chain->edgel(n1).y();
00652     double d1o = (x1-xo)*(x1-xo) + (y1-yo)*(y1-yo);
00653     double d1n = (x1-xn)*(x1-xn) + (y1-yn)*(y1-yn);
00654     if (d1o<d1n)//The expected case
00655     {
00656       // dc->SetX(x1, 0); dc->SetY(y1, 0);
00657       chain->edgel(0).set_x(x1);
00658       chain->edgel(0).set_y(y1);
00659       // dc->SetX(x2, n1); dc->SetY(y2, n1);
00660       chain->edgel(n1).set_x(x2);
00661       chain->edgel(n1).set_y(y2);
00662     }
00663     else
00664     {
00665       // dc->SetX(x2, 0); dc->SetY(y2, 0);
00666       chain->edgel(0).set_x(x2);
00667       chain->edgel(0).set_y(y2);
00668       // dc->SetX(x1, n1); dc->SetY(y1, n1);
00669       chain->edgel(n1).set_x(x1);
00670       chain->edgel(n1).set_y(y1);
00671     }
00672   }
00673   vcl_cout << "Remove Jaggies(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00674 }
00675 
00676 
00677 //: Removal of edges can also produce loops.  Short loops should be removed.
00678 void gevd_clean_edgels::RemoveLoops()
00679 {
00680   vul_timer t;
00681   float min_loop_length = 4.0f;  //6 is normally used in Clean
00682   vcl_vector<vtol_edge_2d_sptr > removed_edges;
00683   for (vcl_vector<vtol_edge_2d_sptr >::iterator egit = out_edgels_->begin();
00684        egit!=out_edgels_->end(); ++egit)
00685   {
00686     vtol_edge_2d_sptr e = (vtol_edge_2d_sptr )(*egit);
00687     vtol_vertex_2d_sptr v1 = e->v1()->cast_to_vertex_2d();
00688     vtol_vertex_2d_sptr v2 = e->v2()->cast_to_vertex_2d();
00689     if (*v1==*v2)//We have a loop
00690     {
00691       vdgl_digital_curve_sptr c = e->curve()->cast_to_vdgl_digital_curve();
00692       double len = c->length();
00693       if (verbose) vcl_cout << "In Remove Loops: "<< v1 << " L = " << len << vcl_endl;
00694       if (len<min_loop_length)
00695       {
00696         // e->unlink_all_inferiors_twoway(e);
00697         // e->unlink_all_inferiors();
00698         removed_edges.push_back(e);
00699       }
00700     }
00701   }
00702 
00703   for (vcl_vector<vtol_edge_2d_sptr >::iterator eit = removed_edges.begin();
00704        eit != removed_edges.end(); ++eit)
00705   {
00706     vcl_vector<vtol_edge_2d_sptr>::iterator f = vcl_find(out_edgels_->begin(), out_edgels_->end(), *eit);
00707     if (f != out_edgels_->end())
00708       out_edgels_->erase(f);
00709   }
00710 
00711   vcl_cout << "Remove Loops(" << out_edgels_->size() << ") in " << t.real() << " msecs.\n";
00712 }

Generated on Thu Jan 10 14:47:16 2008 for contrib/gel/gevd by  doxygen 1.4.4