contrib/brl/bseg/sdet/sdet_contour.h
Go to the documentation of this file.
00001 #ifndef sdet_contour_h_
00002 #define sdet_contour_h_
00003 //:
00004 // \file
00005 // \brief tracing connected contours and junctions
00006 //
00007 // Operator to implement the tracing of connected contours and junctions.
00008 // All contours are assumed chains or cycles with zero width,
00009 // and so can be traced using 4/8-connected pixels.
00010 // Junctions will be detected from end points touching multiple
00011 // other end points, or touching a stronger contour with a significant
00012 // jump in filter response.
00013 // Extensively use the image grid to insure planarity of the network
00014 // of edges and vertices, when projected onto the image plane.
00015 // The recipe is:
00016 //
00017 //    1. Trace 4/8-connected pixels to enumerate disjoint chains
00018 //       and cycles. Prune contours that are either short or have
00019 //       no pixel stronger than a high hysteresis threshold.
00020 //
00021 //    2. Find junctions from end points touching internal
00022 //       pixels of some stronger chain/cycle. Break a stronger
00023 //       contour at a junction, only if there is a detectable
00024 //       jump in filter response.
00025 //       Next, merge end points touching other end points or junctions.
00026 //       Finally, create dummy end point for isolated cycles.
00027 //
00028 //    3. Insert subpixel accuracy into edges/vertices.
00029 //       Because of truncation errors, the mapping from edgel
00030 //       locations to integral grid locations may no longer be
00031 //       preserved, after this step.
00032 //
00033 //    4. Optionally reduce noisy zig-zags along the contours, and
00034 //       evenly space the contour points. The zig-zags are never
00035 //       more than 0.5 pixel, and happen when sub-pixel locations
00036 //       are noisy and so out-of-sync with the 4/8-connected tracing.
00037 //
00038 //    5. Optionally insert virtual border at the image boundary,
00039 //       to form closed region beyond the image boundary.
00040 //
00041 //    6. Insert depth/z values into edges/vertices, through
00042 //       interpolation of the range image, for example.
00043 //       For an intensity image, set this depth to a constant
00044 //       value, since the 3D edges/vertices all lie in the
00045 //       image plane.
00046 //
00047 // Input: connected edge elements, with response strength,
00048 //        and subpixel location, describing isolated contours
00049 //        disjoint only at junction pixels.
00050 //        min_strength and min_length are used to prune weak or
00051 //        short edges. min_jump is used to prune weak junctions.
00052 //
00053 // Output: planar network of linked edges and vertices.
00054 //
00055 // Complexity: O(|edgels|) time and space.
00056 //             O(nlogn) time for quicksort if n=|chains| < 100000,
00057 //             to make sure that junctions are found from
00058 //             longer/stronger chains first.
00059 //
00060 // \author
00061 //  John Canny      (1986) SM Thesis            \and
00062 //  Chris Connolly  (1987) Use Fu-Tsao thinning \and
00063 //  Van-Duc Nguyen  (1989) Eliminate short & weak contours \and
00064 //  Arron Heller    (1992) Translate from CLOS to C++ \and
00065 //  Van-Duc Nguyen  (1995) Trace/search breadth-first instead of thinning \and
00066 //  Joe Mundy       (1997) Added continuous edgel orientation output \and
00067 //  Van-Duc Nguyen  (1998) Merge from end points of dangling chains only \and
00068 //  Joe Mundy       (1999) Modified ::InsertBorder to use ROI bounds
00069 //  Joe Mundy       (2002) Extensive repairs and consolidation after conversion to VXL
00070 //  Peter Vanroose  (2003) removed z coord arg of Translate()
00071 //  Joe Mundy       (2003) [Aug] Eliminate zig-zags in ::FindChains
00072 //-----------------------------------------------------------------------------
00073 
00074 #include <vcl_vector.h>
00075 #include <vbl/vbl_array_2d.h>
00076 #include <vdgl/vdgl_digital_curve_sptr.h>
00077 #include <vtol/vtol_vertex_2d_sptr.h>
00078 #include <vtol/vtol_edge_2d.h>
00079 #include <vtol/vtol_edge_2d_sptr.h>
00080 #include <gevd/gevd_bufferxy.h>
00081 
00082 class sdet_contour
00083 {
00084  public:
00085   sdet_contour(float min_strength, int min_length, // hysteresis
00086                float min_jump,         // jump in strength at junctions
00087                float max_gap=2.236068f); // bridge small gaps (sqrt(5))
00088   ~sdet_contour();
00089 
00090   //: Trace the edgel locations to form a topological network (edges, vertices)
00091   bool FindNetwork(gevd_bufferxy& edgels, bool junctionp,
00092                    const int njunction,
00093                    const int* junctionx, const int* junctiony,
00094                    vcl_vector<vtol_edge_2d_sptr>*& edges,
00095                    vcl_vector<vtol_vertex_2d_sptr >*& vertices);
00096 
00097   //: Use interpolation of the gradient to localize to sub-pixel accuracy
00098   void SubPixelAccuracy(vcl_vector<vtol_edge_2d_sptr>& edges,
00099                         vcl_vector<vtol_vertex_2d_sptr >& vertices,
00100                         const gevd_bufferxy& locationx,
00101                         const gevd_bufferxy& locationy);
00102 
00103   //: Insert a border at the ROI boundary to support connected components
00104   void InsertBorder(vcl_vector<vtol_edge_2d_sptr>& edges,
00105                     vcl_vector<vtol_vertex_2d_sptr >& vertices);
00106 
00107   //: apply a smoothing filter to edgel_chain(s)
00108   static void EqualizeSpacing(vcl_vector<vtol_edge_2d_sptr>& chains);
00109 
00110 
00111   //: computation is carried out in a zero origin ROI - translate back
00112   static void Translate(vcl_vector<vtol_edge_2d_sptr>& edges,
00113                         vcl_vector<vtol_vertex_2d_sptr >& vertices,
00114                         float tx=0.5, float ty = 0.5);
00115 
00116   //: clear network storage (edges and vertices)
00117   static void ClearNetwork(vcl_vector<vtol_edge_2d_sptr>*& edges,
00118                            vcl_vector<vtol_vertex_2d_sptr >*& vertices);
00119 
00120   //: Set edgel gradient and direction values from pixel arrays
00121   static void SetEdgelData(gevd_bufferxy& grad_mag, gevd_bufferxy& angle,
00122                            vcl_vector<vtol_edge_2d_sptr>& edges);
00123 
00124 
00125   void BeSilent() {talkative_ = false;}
00126   void BeTalkative() {talkative_ = true;}
00127   void SetDebug() {debug_ = true;}
00128   void ClearDebug() {debug_ = false;}
00129 
00130   static  bool talkative_; // output comentaries or not
00131   static  bool debug_;
00132 
00133   //: internal routines
00134  protected:
00135   //: link detected edgels and junctions into chains
00136   int FindChains(gevd_bufferxy& edgels,
00137                  const int njunction,
00138                  const int* junctionx, const int* junctiony,
00139                  vcl_vector<vtol_edge_2d_sptr>& edges);
00140 
00141   //: Establish vertices; improve connectivity by jumping small gaps
00142   int FindJunctions(gevd_bufferxy& edgels,
00143                     vcl_vector<vtol_edge_2d_sptr>& edges,
00144                     vcl_vector<vtol_vertex_2d_sptr >& vertices);
00145 
00146   bool move_junction(vtol_vertex_2d_sptr const& junction,
00147                      int& index, vdgl_digital_curve_sptr const & dc);
00148 
00149   void update_edgel_chain(vtol_edge_2d_sptr const& edge,
00150                           const int old_x, const int old_y,
00151                           vtol_vertex_2d_sptr& v);
00152 
00153   bool near_border(vtol_vertex_2d_sptr const&  v);
00154 
00155   //: Detect a nearby vertex by carrying out a spiral search
00156   bool DetectJunction(vtol_vertex_2d_sptr const& end, int& index,
00157                       vtol_edge_2d_sptr& weaker,
00158                       vtol_edge_2d_sptr& stronger,
00159                       const int maxSpiral,
00160                       const gevd_bufferxy& edgels);
00161 
00162   //: Break a chain at a junction and form a "T"
00163   void BreakChain(vtol_vertex_2d_sptr const& junction,
00164                   int& index,
00165                   vtol_edge_2d_sptr const& stronger,
00166                   vtol_edge_2d_sptr& longer,
00167                   vtol_edge_2d_sptr& shorter);
00168 
00169   //: Break a single edge at junction and form a loop
00170   void LoopChain(vtol_vertex_2d_sptr const& junction, int& index,
00171                  vtol_edge_2d_sptr const& chain,
00172                  vtol_edge_2d_sptr& straight,
00173                  vtol_edge_2d_sptr& curled);
00174 
00175   //: Break a closed cycle and insert a vertex at junction
00176     void BreakCycle(vtol_vertex_2d_sptr const& junction,
00177                     int& index, vtol_edge_2d_sptr const& stronger,
00178                     vtol_edge_2d_sptr & split);
00179 
00180   //: Detect nearby vertices by searching in a spiral pattern
00181   vtol_vertex_2d_sptr
00182     DetectTouch(vtol_vertex_2d_sptr const& end, const int maxSpiral);
00183 
00184   //:Connect an isolated endpoint to a nearby single vertex on a different edge
00185  void  MergeEndPtTouchingEndPt(vtol_vertex_2d_sptr const& end1,
00186                                vtol_vertex_2d_sptr const& end2,
00187                                vtol_edge_2d_sptr& merge,
00188                                vtol_edge_2d_sptr& longer,
00189                                vtol_edge_2d_sptr& shorter);
00190 
00191   //:Connect an isolated endpoint to a nearby junction (2 or more edges)
00192  bool  MergeEndPtTouchingJunction(vtol_vertex_2d_sptr const& endpt,
00193                                   vtol_vertex_2d_sptr const& junction,
00194                                   vtol_edge_2d_sptr& old_edge,
00195                                   vtol_edge_2d_sptr& new_edge);
00196 
00197   //:Connect an isolated endpoint to the other vertex on the same edge
00198  bool MergeEndPtsOfChain(vtol_vertex_2d_sptr const& endpt,
00199                          vtol_vertex_2d_sptr const& other,
00200                          vtol_vertex_2d_sptr& removed_vert);
00201 
00202 
00203   //: Lookup table operations for managing mutated vertices and edges
00204 
00205   //: insert an edge into a table indexed by vsol id
00206   static void LookupTableInsert(vcl_vector<vtol_edge_2d_sptr>& set,
00207                                 vtol_edge_2d_sptr elmt);
00208 
00209   //: replace an edge in a table indexed by vsol id
00210   static void LookupTableReplace(vcl_vector<vtol_edge_2d_sptr>& set,
00211                                  vtol_edge_2d_sptr deleted,
00212                                  vtol_edge_2d_sptr inserted);
00213 
00214   //: remove an edge from a table indexed by vsol id
00215   static void LookupTableRemove(vcl_vector<vtol_edge_2d_sptr>& set,
00216                                 vtol_edge_2d_sptr elmt);
00217 
00218   //: eliminate gaps in the table by removing empty entries
00219   static void LookupTableCompress(vcl_vector<vtol_edge_2d_sptr>& set);
00220 
00221 
00222   //: insert a vertex into a table indexed by vsol id
00223   static void LookupTableInsert(vcl_vector<vtol_vertex_2d_sptr >& set,
00224                                 vtol_vertex_2d_sptr  elmt);
00225 
00226   //: replace a vertex in a table indexed by vsol id
00227   static void LookupTableReplace(vcl_vector<vtol_vertex_2d_sptr >& set,
00228                                  vtol_vertex_2d_sptr  deleted,
00229                                  vtol_vertex_2d_sptr  inserted);
00230 
00231   //: remove a vertex from a table indexed by vsol id
00232   static void LookupTableRemove(vcl_vector<vtol_vertex_2d_sptr >& set,
00233                                 vtol_vertex_2d_sptr  elmt);
00234 
00235   //: eliminate gaps in the table by removing empty entries
00236   static void LookupTableCompress(vcl_vector<vtol_vertex_2d_sptr >& set);
00237 
00238   //: class members
00239   float minStrength;  // hysteresis or noise threshold
00240   int minLength;      // number of pixels in shortest chain
00241   float minJump;      // change in strength at junction
00242   float max_gap;      // largest gap to span
00243   int maxSpiral;      // number of spiral search for max_gap
00244   vbl_array_2d<vtol_edge_2d_sptr> *edgeMap;
00245   vbl_array_2d<vtol_vertex_2d_sptr> *vertexMap; // map pixel to junction/chain
00246   vcl_vector<vtol_vertex_2d_sptr> test_verts_;
00247 };
00248 
00249 #endif // sdet_contour_h_