contrib/gel/gevd/gevd_step.h
Go to the documentation of this file.
00001 #ifndef gevd_step_h_
00002 #define gevd_step_h_
00003 //:
00004 // \file
00005 // \brief detection of step profiles in the intensity image
00006 //
00007 // Operator to implement Canny edge detector which finds elongated
00008 // step contours with dG. Then junctions are found by extending
00009 // from end points of dangling contours.
00010 //
00011 // The recipe is:
00012 //    -  Convolution with Gaussian with sigma typically = 1,
00013 //       to well-condition the surface before taking first derivative.
00014 //       Result is a smoothed image.
00015 //
00016 //    -  Convolution with first derivative, or first difference.
00017 //       Result is a gradient image. Canny proves that first-derivative
00018 //       of the Gaussian is the optimum filter to detect elongated
00019 //       step profiles.
00020 //
00021 //    -  Optionally estimate sensor/texture sigma, if given noise
00022 //       sigma is a negative interpolation factor -k in range -[0 1].
00023 //       noise_sigma = (1-k)*sensor_sigma + k*texture_sigma.
00024 //       Sensor and texture sigmas are estimated from the histogram
00025 //       of weak step edges, detected in an ROI centered on gradient image.
00026 //       (see Step constructor documentation in Step.C - JLM)
00027 //
00028 //    -  Non Maximum suppression in the direction of local gradient,
00029 //       to detect pixels with maximum local slope, above a priori
00030 //       noise response. Result is connected contours, width < 2,
00031 //       broken only at junctions with weaker chains.
00032 //       Also obtain subpixel accuracy normal to the contour.
00033 //
00034 //    -  Optionally extend from end points of contours to search for
00035 //       maximum slope in the direction normal to the dangling contours,
00036 //       above some factor of the noise response.
00037 //       Result is a simple detection of all strong junctions.
00038 //
00039 // Input: Intensity image, smoothing sigma, sensor/texture noise sigma
00040 //        and threshold factors for detecting contour/junction edge elements.
00041 //
00042 // Output: Magnitude, direction, location of step pixels, forming
00043 //         a connected network of contours.
00044 //
00045 // Complexity: O(|pixels|) time and space for convolutions.
00046 //             O(|edgels|) time for iterative extension to recover junctions.
00047 //
00048 // \verbatim
00049 // Authors
00050 //  John Canny      (1986) SM Thesis
00051 //  Chris Connolly  (1987) use directional 1st-difference
00052 //  Van-Duc Nguyen  (1989) add subpixel location, extension to find junctions
00053 //  Arron Heller    (1992) translate from CLOS to C++
00054 //  Van-Duc Nguyen  (1995) add noise estimation, use FloatOperators.
00055 //  Joe Mundy       (1997) expanded comments on some methods.  Added gradient
00056 //                         magnitude, grad_mag,  and gradient direction angle
00057 //                         buffer, angle, to cache between edgel detection phases.
00058 // \endverbatim
00059 //-----------------------------------------------------------------------------
00060 
00061 #include <vcl_iosfwd.h>
00062 class gevd_bufferxy;
00063 
00064 class gevd_step
00065 {
00066  public:
00067   gevd_step(float smooth_sigma=1,       //!< spatial smoothing [0.5 2.0]
00068             float noise_sigma=-0.5,     //!< sensor/texture intensity noise -[0 1]
00069             float contour_factor=1.0,   //!< threshold factor for contour edgels
00070             float junction_factor=1.5); //!< threshold factor for junction edgels
00071   ~gevd_step();
00072 
00073   bool DetectEdgels(const gevd_bufferxy& image, //!< float image
00074                     gevd_bufferxy*& edgels, //!< strength = dG * I
00075                     gevd_bufferxy*& direction, //!< direction % PI/4
00076                     gevd_bufferxy*& locationx, //!< subpixel loc
00077                     gevd_bufferxy*& locationy,
00078                     gevd_bufferxy*& grad_mag, //!< Gradient magnitude
00079                     gevd_bufferxy*& angle);    //!< Gradient orientation
00080   int RecoverJunctions(const gevd_bufferxy& image, //!< iterative extension
00081                        gevd_bufferxy& edgels, //!< from end points of contours
00082                        gevd_bufferxy& direction,
00083                        gevd_bufferxy& locationx, gevd_bufferxy& locationy,
00084                        int*& junctionx, int*& junctiony);
00085 
00086   float NoiseSigma() const;     //!< query stored/estimated noise sigma
00087   float NoiseResponse() const;  //!< response of noise sigma to filter ddG
00088   float NoiseThreshold(bool shortp=false) const; //!< elongated/directional?
00089 
00090   static float NoiseResponseToFilter(const float noiseSigma,
00091                                      const float smoothSigma,
00092                                      const float filterFactor);
00093 
00094   friend vcl_ostream& operator<<(vcl_ostream& os, const gevd_step& st);
00095   friend vcl_ostream& operator<<(vcl_ostream& os, gevd_step& st);
00096 
00097  protected:
00098   float smoothSigma;                   //!< spatial smoothing
00099   float noiseSigma;                    //!< sensor/texture noise
00100   float contourFactor, junctionFactor; //!< threshold factor for edgels
00101   float filterFactor;                  //!< factor in convolution filter
00102 };
00103 
00104 #endif // gevd_step_h_