1 #ifndef gevd_step_h_
2 #define gevd_step_h_
3 //:
4 // \file
5 // \brief detection of step profiles in the intensity image
6 //
7 // Operator to implement Canny edge detector which finds elongated
8 // step contours with dG. Then junctions are found by extending
9 // from end points of dangling contours.
10 //
11 // The recipe is:
12 //    -  Convolution with Gaussian with sigma typically = 1,
13 //       to well-condition the surface before taking first derivative.
14 //       Result is a smoothed image.
15 //
16 //    -  Convolution with first derivative, or first difference.
17 //       Result is a gradient image. Canny proves that first-derivative
18 //       of the Gaussian is the optimum filter to detect elongated
19 //       step profiles.
20 //
21 //    -  Optionally estimate sensor/texture sigma, if given noise
22 //       sigma is a negative interpolation factor -k in range -[0 1].
23 //       noise_sigma = (1-k)*sensor_sigma + k*texture_sigma.
24 //       Sensor and texture sigmas are estimated from the histogram
25 //       of weak step edges, detected in an ROI centered on gradient image.
26 //       (see Step constructor documentation in Step.C - JLM)
27 //
28 //    -  Non Maximum suppression in the direction of local gradient,
29 //       to detect pixels with maximum local slope, above a priori
30 //       noise response. Result is connected contours, width < 2,
31 //       broken only at junctions with weaker chains.
32 //       Also obtain subpixel accuracy normal to the contour.
33 //
34 //    -  Optionally extend from end points of contours to search for
35 //       maximum slope in the direction normal to the dangling contours,
36 //       above some factor of the noise response.
37 //       Result is a simple detection of all strong junctions.
38 //
39 // Input: Intensity image, smoothing sigma, sensor/texture noise sigma
40 //        and threshold factors for detecting contour/junction edge elements.
41 //
42 // Output: Magnitude, direction, location of step pixels, forming
43 //         a connected network of contours.
44 //
45 // Complexity: O(|pixels|) time and space for convolutions.
46 //             O(|edgels|) time for iterative extension to recover junctions.
47 //
48 // \verbatim
49 // Authors
50 //  John Canny      (1986) SM Thesis
51 //  Chris Connolly  (1987) use directional 1st-difference
52 //  Van-Duc Nguyen  (1989) add subpixel location, extension to find junctions
53 //  Arron Heller    (1992) translate from CLOS to C++
54 //  Van-Duc Nguyen  (1995) add noise estimation, use FloatOperators.
55 //  Joe Mundy       (1997) expanded comments on some methods.  Added gradient
56 //                         magnitude, grad_mag,  and gradient direction angle
57 //                         buffer, angle, to cache between edgel detection phases.
58 // \endverbatim
59 //-----------------------------------------------------------------------------
60 
61 #include <iostream>
62 #include <iosfwd>
63 #ifdef _MSC_VER
64 #  include <vcl_msvc_warnings.h>
65 #endif
66 class gevd_bufferxy;
67 
68 class gevd_step
69 {
70  public:
71   gevd_step(float smooth_sigma=1,       //!< spatial smoothing [0.5 2.0]
72             float noise_sigma=-0.5,     //!< sensor/texture intensity noise -[0 1]
73             float contour_factor=1.0,   //!< threshold factor for contour edgels
74             float junction_factor=1.5); //!< threshold factor for junction edgels
75   ~gevd_step();
76 
77   bool DetectEdgels(const gevd_bufferxy& image, //!< float image
78                     gevd_bufferxy*& edgels, //!< strength = dG * I
79                     gevd_bufferxy*& direction, //!< direction % PI/4
80                     gevd_bufferxy*& locationx, //!< subpixel loc
81                     gevd_bufferxy*& locationy,
82                     gevd_bufferxy*& grad_mag, //!< Gradient magnitude
83                     gevd_bufferxy*& angle);    //!< Gradient orientation
84   int RecoverJunctions(const gevd_bufferxy& image, //!< iterative extension
85                        gevd_bufferxy& edgels, //!< from end points of contours
86                        gevd_bufferxy& direction,
87                        gevd_bufferxy& locationx, gevd_bufferxy& locationy,
88                        int*& junctionx, int*& junctiony) const;
89 
90   float NoiseSigma() const;     //!< query stored/estimated noise sigma
91   float NoiseResponse() const;  //!< response of noise sigma to filter ddG
92   float NoiseThreshold(bool shortp=false) const; //!< elongated/directional?
93 
94   static float NoiseResponseToFilter(const float noiseSigma,
95                                      const float smoothSigma,
96                                      const float filterFactor);
97 
98   friend std::ostream& operator<<(std::ostream& os, const gevd_step& st);
99   friend std::ostream& operator<<(std::ostream& os, gevd_step& st);
100 
101  protected:
102   float smoothSigma;                   //!< spatial smoothing
103   float noiseSigma;                    //!< sensor/texture noise
104   float contourFactor, junctionFactor; //!< threshold factor for edgels
105   float filterFactor{2};               //!< factor in convolution filter
106 };
107 
108 #endif // gevd_step_h_
109