Ocean
FrameFilterCanny.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_CV_FRAME_FILTER_CANNY_H
9 #define META_OCEAN_CV_FRAME_FILTER_CANNY_H
10 
11 #include "ocean/cv/CV.h"
12 
13 #include "ocean/base/Worker.h"
14 
15 #include "ocean/cv/PixelPosition.h"
16 
17 namespace Ocean
18 {
19 
20 namespace CV
21 {
22 
23 /**
24  * This class implements a canny edge filter based on Sobel or Scharr filter operators and their responses respectively.
25  * @ingroup cv
26  */
27 class OCEAN_CV_EXPORT FrameFilterCanny
28 {
29  protected:
30 
31  /**
32  * Definition of individual edge filter operators.
33  */
35  {
36  /// Sobel operator
38  /// Scharr operator
39  EF_SCHARR
40  };
41 
42  /**
43  * Definition of individual edge directions.
44  */
46  {
47  /// Unknown edge direction.
48  ED_UNKNOWN = 0,
49  /// Horizontal edge with 0 degree.
51  /// Diagonal edge with 45 degree
53  /// Vertical edge with 90 degree.
55  /// Diagonal edige with 135 degree.
57  /// No edge.
58  ED_NO_EDGE
59  };
60 
61  public:
62 
63  /**
64  * Canny edge detector for 8 bit grayscale images using a normalized Sobel operator<br>
65  * Applies a normalized Sobel filter in four directions: 0, 90, 45, and 135 degrees, value range: [-127, 127]. For thresholding the absolute value of the filter response will be used.<br>
66  * Pixels along the border of the source image are never considered for edges (first/last column/row).
67  * @param source The source frame (8-bit, 1 channel image), must be a valid
68  * @param target The frame that will contain extracted Canny edges (8-bit, 1 channel image, same size as `source`), must be valid
69  * @param width The width of the source frame in pixels, range: [3, infinity)
70  * @param height The height of the source frame in pixels, range: [3, infinity)
71  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
72  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
73  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: [0, 127], default: 20
74  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: (lowThreshold, 127], default: 50
75  * @param worker An optional worker object for parallelization
76  */
77  static void filterCannySobelNormalized(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int8_t lowThreshold = 20, const int8_t highThreshold = 50, Worker* worker = nullptr);
78 
79  /**
80  * Canny edge detector for 8 bit grayscale images using a Sobel operator<br>
81  * Applies an (unnormalized) Sobel filter in four directions: 0, 90, 45, and 135 degrees, value range: [-1020, 1020]. For thresholding the absolute value of the filter response will be used.<br>
82  * Pixels along the border of the source image are never considered for edges (first/last column/row).
83  * @param source The source frame (8-bit, 1 channel image), must be a valid
84  * @param target The frame that will contain extracted Canny edges (8-bit, 1 channel image, same size as `source`), must be valid
85  * @param width The width of the source frame in pixels, range: [3, infinity)
86  * @param height The height of the source frame in pixels, range: [3, infinity)
87  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
88  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
89  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: [0, 1020], default: 160
90  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: (lowThreshold, 1020], default: 400
91  * @param worker An optional worker object for parallelization
92  */
93  static void filterCannySobel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int16_t lowThreshold = 160, const int16_t highThreshold = 400, Worker* worker = nullptr);
94 
95  /**
96  * Canny edge detector for 8 bit grayscale images using a normalized Scharr operator<br>
97  * Applies a normalized Scharr filter in four directions: 0, 90, 45, and 135 degrees, value range: [-127, 127]. For thresholding the absolute value of the filter response will be used.<br>
98  * Pixels along the border of the source image are never considered for edges (first/last column/row).
99  * @param source The source frame (8-bit, 1 channel image), must be a valid
100  * @param target The frame that will contain extracted Canny edges (8-bit, 1 channel image, same size as `source`), must be valid
101  * @param width The width of the source frame in pixels, range: [3, infinity)
102  * @param height The height of the source frame in pixels, range: [3, infinity)
103  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
104  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
105  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: [0, 127], default: 20
106  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: (lowThreshold, 127], default: 50
107  * @param worker An optional worker object for parallelization
108  */
109  static void filterCannyScharrNormalized(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int8_t lowThreshold = 20, const int8_t highThreshold = 50, Worker* worker = nullptr);
110 
111  /**
112  * Canny edge detector for 8 bit grayscale images using a Scharr operator<br>
113  * Applies an (unnormalized) Scharr filter in four directions: 0, 90, 45, and 135 degrees, value range: [-4080, 4080]. For thresholding the absolute value of the filter response will be used.<br>
114  * Pixels along the border of the source image are never considered for edges (first/last column/row).
115  * @param source The source frame (8-bit, 1 channel image), must be a valid
116  * @param target The frame that will contain extracted Canny edges (8-bit, 1 channel image, same size as `source`), must be valid
117  * @param width The width of the source frame in pixels, range: [3, infinity)
118  * @param height The height of the source frame in pixels, range: [3, infinity)
119  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
120  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
121  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: [0, 4080], default: 640
122  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: (lowThreshold, 4080], default: 1600
123  * @param worker An optional worker object for parallelization
124  */
125  static void filterCannyScharr(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int16_t lowThreshold = 640, const int16_t highThreshold = 1600, Worker* worker = nullptr);
126 
127  private:
128 
129  /**
130  * Canny edge filter for 8 bit gray scale images for 0, 90, 45, and 135 degrees.<br>
131  * The border pixels are set to unknown edge directions.
132  * @param source The source frame to filter, must be valid
133  * @param target The target frame receiving the filtered frame, must be valid
134  * @param width The width of the frame in pixel, with range [3, infinity)
135  * @param height The height of the frame in pixel, with range [3, infinity)
136  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
137  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
138  * @param lowThreshold The threshold for not being edges [0, 127]
139  * @param highThreshold The threshold for surely being edges (lowThreshold, 127]
140  * @param worker An optional worker object to distribute the computational load
141  * @tparam TFilterOutputElementType The element type of the filter output, cf. parameter `filterFunction`, e.g., `int8_t` or `int16_t`
142  * @tparam tEdgeFilter The filter function that is used to determine the horizontal, vertical, diagonal directions (0, 90, 45, 135 degree), must be valid.
143  */
144  template <typename TFilterOutputElementType, EdgeFilter tEdgeFilter>
145  static void filterCanny(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, Worker* worker = nullptr);
146 
147  /**
148  * Calculates edge directions (quantized to 0, 90, 45, and 135 degrees) and their corresponding magnitues (based on Sobel or Scharr filter responses).
149  * @param egdeFilterResults Source: filter response of scharr filter (zipped frame for each degree)
150  * @param direction The target receiving the quantized edge directions.
151  * @param magnitude The target receiving the edge magnitudes.
152  * @param lowThreshold The threshold for not being edges
153  * @param width The width of the frame in pixel, with range [3, infinity)
154  * @param height The height of the frame in pixel, with range [3, infinity)
155  * @param worker An optional worker object to distribute the computational load
156  * @tparam T The data type of the edge operator responses
157  */
158  template <typename T>
159  static inline void extractGradientDirectionsAndMagnitudes(const T* egdeFilterResults, uint8_t* direction, T* magnitude, const T lowThreshold, const unsigned int width, const unsigned int height, Worker* worker = nullptr);
160 
161  /**
162  * Calculates a subset of edge directions (quantized to 0, 90, 45, and 135 degrees) and their corresponding magnitues (based on Sobel or Scharr filter responses).
163  * @param egdeFilterResults Source: filter response of scharr filter (zipped frame for each degree)
164  * @param direction The target receiving the quantized edge directions.
165  * @param magnitude The target receiving the edge magnitudes.
166  * @param lowThreshold The threshold for not being edges
167  * @param width The width of the frame in pixel, with range [3, infinity)
168  * @param height The height of the frame in pixel, with range [3, infinity)
169  * @param firstRow First row to be filtered
170  * @param numberRows Number of rows to be filtered
171  * @tparam T The data type of the edge operator responses
172  */
173  template <typename T>
174  static void extractGradientDirectionsAndMagnitudesSubset(const T* egdeFilterResults, uint8_t* direction, T* magnitude, const T lowThreshold, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows);
175 
176  /**
177  * Extract edges from the gradient magnitudes and directions
178  * @param gradientDirections The frame containing the binned directions of the gradient (0, 90, 45, 135), must be valid
179  * @param gradientMagnitudes The frame containing the absolute gradient magnitudes, must be valid
180  * @param target The frame that will contain extracted Canny edges, must be valid (8-bit, 1 channel image, size: width x height)
181  * @param width The width of the frames in pixels, range: [3, infinity)
182  * @param height The height of the frames in pixels, range: [3, infinity)
183  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
184  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: 8-bit Sobel/Scharr: [0, 126], 16-bit Sobel [0, 1019], 16-bit Scharr: [0, 4079]
185  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: 8-bit Sobel/Scharr: [lowThreshold, 127], 16-bit Sobel [0, 1020], 16-bit Scharr: [0, 4080]
186  * @param worker An optional worker object for parallelization
187  */
188  template <typename TFilterOutputElementType>
189  static void extractEdgePixels(const uint8_t* const gradientDirections, const TFilterOutputElementType* const gradientMagnitudes, uint8_t* const target, const unsigned int width, const unsigned int height, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, Worker* worker = nullptr);
190 
191  /**
192  * Helper function to extract edges from the gradient magnitudes and directions
193  * @param gradientDirections The frame containing the binned directions of the gradient (0, 90, 45, 135), must be valid
194  * @param gradientMagnitudes The frame containing the absolute gradient magnitudes, must be valid
195  * @param target The frame that will contain extracted Canny edges, must be valid (8-bit, 1 channel image, size: width x height)
196  * @param edgeCandidateMap The map of edge candidates
197  * @param edgeCandidateStack The resulting edge candidates, must be valid
198  * @param edgeCandidateStackLock The lock for the stack of edge candidates
199  * @param width The width of the frames in pixels, range: [3, infinity)
200  * @param height The height of the frames in pixels, range: [3, infinity)
201  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
202  * @param lowThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately rejected as edges, range: 8-bit Sobel/Scharr: [0, 126], 16-bit Sobel [0, 1019], 16-bit Scharr: [0, 4079]
203  * @param highThreshold After filtering the source image (cf. `tEdgeFilter`), pixels with an absolute filter response below this threshold will be immediately accepted as edges if they are local maxima (non-maximum suppression), range: 8-bit Sobel/Scharr: [lowThreshold, 127], 16-bit Sobel [0, 1020], 16-bit Scharr: [0, 4080]
204  * @param firstRow The first row to be handled, with range [0, height - 1]
205  * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
206  */
207  template <typename TFilterOutputElementType>
208  static void extractEdgePixelsSubset(const uint8_t* const gradientDirections, const TFilterOutputElementType* const gradientMagnitudes, uint8_t* const target, uint8_t* const edgeCandidateMap, CV::PixelPositions* edgeCandidateStack, Lock* edgeCandidateStackLock, const unsigned int width, const unsigned int height, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, const unsigned int firstRow, const unsigned numberRows);
209 };
210 
211 template <typename T>
212 inline void FrameFilterCanny::extractGradientDirectionsAndMagnitudes(const T* egdeFilterResults, uint8_t* direction, T* magnitude, const T lowThreshold, const unsigned int width, const unsigned int height, Worker* worker)
213 {
214  if (worker)
215  {
216  worker->executeFunction(Worker::Function::createStatic(&extractGradientDirectionsAndMagnitudesSubset, egdeFilterResults, direction, magnitude, lowThreshold, width, height, 0u, 0u), 0, height, 6u, 7u, 20u);
217  }
218  else
219  {
220  extractGradientDirectionsAndMagnitudesSubset(egdeFilterResults, direction, magnitude, lowThreshold, width, height, 0u, height);
221  }
222 }
223 
224 } // namespace CV
225 
226 } // namespace Ocean
227 
228 #endif // META_OCEAN_CV_FRAME_FILTER_CANNY_H
This class implements a canny edge filter based on Sobel or Scharr filter operators and their respons...
Definition: FrameFilterCanny.h:28
static void filterCannyScharrNormalized(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int8_t lowThreshold=20, const int8_t highThreshold=50, Worker *worker=nullptr)
Canny edge detector for 8 bit grayscale images using a normalized Scharr operator Applies a normaliz...
static void extractEdgePixelsSubset(const uint8_t *const gradientDirections, const TFilterOutputElementType *const gradientMagnitudes, uint8_t *const target, uint8_t *const edgeCandidateMap, CV::PixelPositions *edgeCandidateStack, Lock *edgeCandidateStackLock, const unsigned int width, const unsigned int height, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, const unsigned int firstRow, const unsigned numberRows)
Helper function to extract edges from the gradient magnitudes and directions.
static void extractGradientDirectionsAndMagnitudes(const T *egdeFilterResults, uint8_t *direction, T *magnitude, const T lowThreshold, const unsigned int width, const unsigned int height, Worker *worker=nullptr)
Calculates edge directions (quantized to 0, 90, 45, and 135 degrees) and their corresponding magnitue...
Definition: FrameFilterCanny.h:212
static void filterCannySobelNormalized(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int8_t lowThreshold=20, const int8_t highThreshold=50, Worker *worker=nullptr)
Canny edge detector for 8 bit grayscale images using a normalized Sobel operator Applies a normalize...
static void filterCannyScharr(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int16_t lowThreshold=640, const int16_t highThreshold=1600, Worker *worker=nullptr)
Canny edge detector for 8 bit grayscale images using a Scharr operator Applies an (unnormalized) Sch...
static void filterCannySobel(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const int16_t lowThreshold=160, const int16_t highThreshold=400, Worker *worker=nullptr)
Canny edge detector for 8 bit grayscale images using a Sobel operator Applies an (unnormalized) Sobe...
static void extractEdgePixels(const uint8_t *const gradientDirections, const TFilterOutputElementType *const gradientMagnitudes, uint8_t *const target, const unsigned int width, const unsigned int height, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, Worker *worker=nullptr)
Extract edges from the gradient magnitudes and directions.
EdgeDirection
Definition of individual edge directions.
Definition: FrameFilterCanny.h:46
@ ED_HORIZONTAL
Horizontal edge with 0 degree.
Definition: FrameFilterCanny.h:50
@ ED_DIAGONAL_45
Diagonal edge with 45 degree.
Definition: FrameFilterCanny.h:52
@ ED_VERTICAL
Vertical edge with 90 degree.
Definition: FrameFilterCanny.h:54
@ ED_DIAGONAL_135
Diagonal edige with 135 degree.
Definition: FrameFilterCanny.h:56
static void extractGradientDirectionsAndMagnitudesSubset(const T *egdeFilterResults, uint8_t *direction, T *magnitude, const T lowThreshold, const unsigned int width, const unsigned int height, const unsigned int firstRow, const unsigned int numberRows)
Calculates a subset of edge directions (quantized to 0, 90, 45, and 135 degrees) and their correspond...
static void filterCanny(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const TFilterOutputElementType lowThreshold, const TFilterOutputElementType highThreshold, Worker *worker=nullptr)
Canny edge filter for 8 bit gray scale images for 0, 90, 45, and 135 degrees.
EdgeFilter
Definition of individual edge filter operators.
Definition: FrameFilterCanny.h:35
@ EF_SOBEL
Sobel operator.
Definition: FrameFilterCanny.h:37
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition: Caller.h:2876
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition: PixelPosition.h:48
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15