00001 //-*- c++ -*------------------------------------------------------------------- 00002 #ifndef osl_edge_detector_h 00003 #define osl_edge_detector_h 00004 //: 00005 // \file 00006 // \brief Charlie's topological edge detector 00007 // 00008 // A class for performing topologically-accurate edgel detection. NB: this 00009 // implementation is (unintentionally) stochastic, so you don't necessarily 00010 // get the same results from the same image. 00011 // 00012 // The basic implementation is based on that described in Canny's thesis 00013 // in that we compute the norm of the gradient, but then we use 00014 // non-maximal suppression dynamically to set the edge strength 00015 // thresholds. Non-maximal suppression is actually done using a 00016 // variant of Tsai-Fu thinning, and not as described in Canny's 00017 // thesis. 00018 // 00019 // Full documentation is given in INRIA technical report 2444, 1994. 00020 // 00021 // \author Charlie Rothwell - 5/10/94 00022 // INRIA, Sophia Antipolis 00023 // 00024 // \verbatim 00025 // Modifications: 00026 // CAR March 1995: improved memory management so that computation 00027 // time is reduced. Re-use of certain large arrays. Tried to 00028 // re-write Set_thresholds() to use Delauney triangulation rather 00029 // than Chamfer filtering. This didn't work as computation time 00030 // became far too high. 00031 // 00032 // JLM May 1995: Added a mask in Compute_gradient to support 00033 // edge detection within a polygonal region. Should add a similar 00034 // test in smoothing and derivative iterations for maximum 00035 // efficiency, but it isn't clear that there would be a big overall 00036 // gain, given the computation of IsMasked(x,y). 00037 // 00038 // JLM May 1995: Added a histogram of edgel strengths as an 00039 // additional output to support edgel change detection. The 00040 // histogram is constructed in Set_thresholds 00041 // 00042 // JLM May 1995 Added a new Do_edge_detector signature 00043 // to output an edgel group which bundles edgel chains and 00044 // gradient statistics together. 00045 // 00046 // JLM May 1997 Modified the formation of the gradient histogram 00047 // computation so that values are accumulated only 00048 // along edgel chains. New accumulation is in 00049 // Follow_curves(edges). The old code is still in place 00050 // but commented out. (Look for "May") The old code 00051 // just histogrammed the gradient magnitude. 00052 // JLM June 1997 Found a bug in the above change which failed if 00053 // ghist_ is NULL. 00054 // JLM Dec 1997 Moved sigma_, low_, gauss_tail_ and verbose_ 00055 // up to osl_edge_detector_params and added new syle 00056 // constructors and execution 00057 // \endverbatim 00058 //----------------------------------------------------------------------------- 00059 00060 #include <osl/osl_canny_port.h> 00061 #include <osl/osl_edge_detector_params.h> 00062 #include <vil1/vil1_image.h> 00063 00064 struct osl_edge_detector : public osl_edge_detector_params 00065 { 00066 osl_edge_detector(osl_edge_detector_params const &); 00067 00068 ~osl_edge_detector(); 00069 00070 void detect_edges(vil1_image const &image, 00071 vcl_list<osl_edge*> *edges, 00072 bool maintain_topology = true); 00073 00074 private: 00075 void Sub_pixel_interpolation(); 00076 void Thicken_threshold(int,int); 00077 void Set_thresholds(); 00078 void Fill_holes(); 00079 void Thin_edges(); 00080 void Follow_curves(vcl_list<osl_edge*>*); 00081 void Follow(int,int,vcl_list<int>*,vcl_list<int>*,vcl_list<float>*,int); 00082 00083 void Find_junctions(); 00084 void Find_junction_clusters(); 00085 void Follow_junctions(int,int,vcl_list<int>*,vcl_list<int>*); 00086 void Cluster_centre(vcl_list<int>&,vcl_list<int>&,int&,int&); 00087 00088 private: 00089 unsigned int width_; // The smoothing kernel width 00090 unsigned int k_size_; // The kernel is 2*width_+1s 00091 float *kernel_; // 1-Dimensional convolution kernel of size k_size 00092 00093 unsigned int xstart_,ystart_; // The origin of the buffer in the image 00094 unsigned int xsize_,ysize_; // The width of the image buffer 00095 00096 float **dx_; // Derivatives in x, and sub-pixel x coordinates 00097 float **dy_; // Derivatives in y, and sub-pixel y coordinates 00098 float **grad_; // Gradient image, and various other storage images 00099 float **smooth_; // Smoothed image. 00100 00101 // Quite a few of the following could be done using hash tables 00102 float **thin_; // Gradient image after thinning 00103 float **theta_; // Orientation image 00104 float **thresh_; // Image of the different thresholds used (replacing low) 00105 00106 int **dist_; // Distance transform image 00107 int **junction_; // Image true only at junctions ends, and relevant lists 00108 int **jx_,**jy_; // Images of (x,y) coordinates of nearest cluster centre 00109 vcl_list<int> *xjunc_,*yjunc_; 00110 vcl_list<osl_Vertex*> *vlist_; // The junction cluster centres 00111 00112 float jval_; // A dummy junction intensity step value 00113 int chain_no_; // A dummy variable used in following 00114 00115 int vertidcount_; // A counter used for setting vertex identifiers 00116 00117 // Added a histogram of edge gradient magnitudes - JLM May 1995 00118 bool gradient_histogram_; // Do we need to compute one? 00119 float max_gradient_; // Added May 1997 - JLM 00120 int histogram_resolution_; // The number of buckets in the histogram 00121 //Histogram* ghist_; 00122 }; 00123 00124 #endif // osl_edge_detector_h