Ocean
FrameFilterGradient.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_GRADIENT_H
9 #define META_OCEAN_CV_FRAME_FILTER_GRADIENT_H
10 
11 #include "ocean/cv/CV.h"
13 
14 #include "ocean/base/Worker.h"
15 
16 namespace Ocean
17 {
18 
19 namespace CV
20 {
21 
22 /**
23  * This class implements a gradient frame filter.
24  * @ingroup cv
25  */
27 {
28  public:
29 
30  /**
31  * Horizontal and vertical gradient filter for a 1-plane frame with arbitrary data type and arbitrary number of channels.
32  * The horizontal and vertical filter responses are stored in a 1-plane response frame so that for each pixel and channel two corresponding filter results exist (interleaved).<br>
33  * The border response pixel results are set to zero.
34  * @param source The source frame to filter, must be valid
35  * @param target The filter response with two filter response elements per pixel and channel, must be valid
36  * @param width The width of the frame in pixel, with range [3, infinity)
37  * @param height The height of the frame in pixel, with range [3, infinity)
38  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
39  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
40  * @param multiplicationFactor Multiplication factor that is applied to each filter result before the value is assigned to the target, with range (-infinity, infinity)
41  * @param worker Optional worker object to distribute the computational load
42  * @tparam TSource The data type of the source frame
43  * @tparam TTarget The data type of the target frame
44  * @tparam tChannels The number of the source frame, with range [1, infinity)
45  * @tparam tNormalizeByTwo True, to normalize the subtraction result by two; False, to simply determine the subtraction result
46  * @see filterHorizontalVerticalSubFrame(), filterHorizontalVerticalMagnitudeSquared().
47  */
48  template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
49  static inline void filterHorizontalVertical(const TSource* source, TTarget* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const TTarget multiplicationFactor = TTarget(1), Worker* worker = nullptr);
50 
51  /**
52  * Squared magnitude gradient filter using the horizontal and vertical gradients that can be applied to zipped frames with arbitrary data type and arbitrary number of channels.
53  * The border pixel results are set to zero.<br>
54  * The two individual filter responses are collected, applied as a vector and the vector's squared length is stored as result.<br>
55  * Thus, for each pixel and each channel one filter response is created.
56  * @param source The source frame to filter, must be valid
57  * @param target Filter response with one filter response (the squared magnitude of the gradient) per pixel and channel
58  * @param width The width of the frame in pixel, with range [3, infinity)
59  * @param height The height of the frame in pixel, with range [3, infinity)
60  * @param multiplicationFactor Multiplication factor that is applied to each filter result before the value is assigned to the target, with range (-infinity, infinity)
61  * @param worker Optional worker object to distribute the computational load
62  * @tparam TSource The data type of the source frame
63  * @tparam TTarget The data type of the target frame
64  * @tparam tChannels The number of the source frame, with range [1, infinity)
65  * @tparam tNormalizeByTwo True, to normalize the subtraction result by two; False, to simply determine the subtraction result
66  * @see filterHorizontalVertical().
67  */
68  template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
69  static inline void filterHorizontalVerticalMagnitudeSquared(const TSource* source, TTarget* target, const unsigned int width, const unsigned int height, const TTarget multiplicationFactor = TTarget(1), Worker* worker = nullptr);
70 
71  /**
72  * Horizontal and vertical gradient filter for sub-frame of a 1-plane frame with arbitrary data type and arbitrary number of channels.
73  * In contrast to filterHorizontalVertical(), this function does not set border response pixels to zero in case the border of the sub-frame is not located at the border of the source frame.
74  * @param source The source frame to filter, must be valid
75  * @param sourceWidth The width of the source frame in pixel, with range [3, infinity)
76  * @param sourceHeight the height of the source frame in pixel, with range [3, infinity)
77  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
78  * @param sourceLeft Horizontal start position of the sub-frame inside the source frame, in pixels, with range [0, sourceWidth)
79  * @param sourceTop Vertical start position of the sub-frame inside the source frame, in pixels, with range [0, sourceHeight)
80  * @param target The filter response with two elements per pixel and channel with dimension targetWidth x targetHeight, must be valid
81  * @param targetWidth The width of the sub-frame inside the source frame (and thus the width of the target response frame), in pixels, with range [1, sourceWidth - sourceLeft]
82  * @param targetHeight The height of the sub-frame inside the source frame (and thus the height of the target response frame), in pixels, with range [1, sourceHeight - sourceTop]
83  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
84  * @param multiplicationFactor Multiplication factor that is applied to each filter result before the value is assigned to the target, with range (-infinity, infinity)
85  * @param worker Optional worker object to distribute the computational load
86  * @tparam TSource The data type of the source frame
87  * @tparam TTarget The data type of the target frame
88  * @tparam tChannels The number of the source frame, with range [1, infinity)
89  * @tparam tNormalizeByTwo True, to normalize the subtraction result by two; False, to simply determine the subtraction result
90  * @see filterHorizontalVertical().
91  */
92  template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
93  static inline void filterHorizontalVerticalSubFrame(const TSource* source, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int sourceLeft, const unsigned int sourceTop, TTarget* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const TTarget multiplicationFactor = TTarget(1), Worker* worker = nullptr);
94 
95  /**
96  * Determines the lined integral image of the horizontal 1x2 gradient filter when applied to a source image.
97  * The function applies the following 1x2 box filter to each pixel of the source image:
98  * <pre>
99  * [-1. 1]
100  * </pre>
101  * The response value will be stored at the location of the left filter pixel (marked with a dot `.`).
102  * The intermediate (internal only) response image has resolution (width-1)x(height).
103  * The resulting (lined) integral response image has the following scheme:
104  * <pre>
105  * ------------
106  * |000000000000|
107  * |0|----------|
108  * |0| |
109  * |0| Integral |
110  * |0| |
111  * ------------
112  * </pre>
113  * The resolution of the (lined) integral image is: (width)x(height + 1).
114  * @param source The source image to which the horizontal gradient filter will be applied, with resolution (width)x(height), must be valid
115  * @param width The width of the source image in pixel, with range [2, infinity)
116  * @param height The height of the source image in pixel, with range [1, infinity)
117  * @param integral The resulting integral image, with resolution (width)x(height + 1), must be valid
118  * @param sourcePaddingElements Optional number of padding elements at the end of each row of the source frame, in elements, with range [0, infinity)
119  * @param integralPaddingElements Optional number of padding elements at the end of each row of the integral frame, in elements, with range [0, infinity)
120  * @tparam T The data type of the elements in the source image
121  * @tparam TIntegral The data type of the elements in the integral image
122  * @tparam tAbsoluteGradient True, to determine the absolute gradients; False, to determine the signed gradients
123  */
124  template <typename T, typename TIntegral, bool tAbsoluteGradient = false>
125  static void filterHorizontal1x2LinedIntegralImage(const T* source, const unsigned int width, const unsigned int height, TIntegral* integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements);
126 
127  /**
128  * Determines the lined integral image of the vertical 2x1 gradient filter when applied to a source image.
129  * The function applies the following 2x1 box filter to each pixel of the source image:
130  * <pre>
131  * [ -1. ]
132  * [ 1 ]
133  * </pre>
134  * The response value will be stored at the location of the left filter pixel (marked with a dot `.`).
135  * The intermediate (internal only) response image has resolution (width)x(height - 1).
136  * The resulting (lined) integral response image has the following scheme:
137  * <pre>
138  * ------------
139  * |000000000000|
140  * |0|----------|
141  * |0| |
142  * |0| Integral |
143  * |0| |
144  * ------------
145  * </pre>
146  * The resolution of the (lined) integral image is: (width + 1)x(height).
147  * @param source The source image to which the horizontal gradient filter will be applied, with resolution (width)x(height), must be valid
148  * @param width The width of the source image in pixel, with range [1, infinity)
149  * @param height The height of the source image in pixel, with range [2, infinity)
150  * @param integral The resulting integral image, with resolution (width + 1)x(height), must be valid
151  * @param sourcePaddingElements Optional number of padding elements at the end of each row of the source frame, in elements, with range [0, infinity)
152  * @param integralPaddingElements Optional number of padding elements at the end of each row of the integral frame, in elements, with range [0, infinity)
153  * @tparam T The data type of the elements in the source image
154  * @tparam TIntegral The data type of the elements in the integral image
155  * @tparam tAbsoluteGradient True, to determine the absolute gradients; False, to determine the signed gradients
156  */
157  template <typename T, typename TIntegral, bool tAbsoluteGradient = false>
158  static void filterVertical2x1LinedIntegralImage(const T* source, const unsigned int width, const unsigned int height, TIntegral* integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements);
159 };
160 
161 template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
162 inline void FrameFilterGradient::filterHorizontalVertical(const TSource* source, TTarget* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const TTarget multiplicationFactor, Worker* worker)
163 {
164  FrameFilterGradientBase::filterHorizontalVertical<TSource, TTarget, tChannels, tNormalizeByTwo>(source, target, width, height, sourcePaddingElements, targetPaddingElements, multiplicationFactor, worker);
165 }
166 
167 template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
168 inline void FrameFilterGradient::filterHorizontalVerticalMagnitudeSquared(const TSource* source, TTarget* target, const unsigned int width, const unsigned int height, const TTarget multiplicationFactor, Worker* worker)
169 {
170  FrameFilterGradientBase::filterHorizontalVerticalMagnitudeSquared<TSource, TTarget, tChannels, tNormalizeByTwo>(source, target, width, height, multiplicationFactor, worker);
171 }
172 
173 template <typename TSource, typename TTarget, unsigned int tChannels, bool tNormalizeByTwo>
174 inline void FrameFilterGradient::filterHorizontalVerticalSubFrame(const TSource* source, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int sourceLeft, const unsigned int sourceTop, TTarget* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const TTarget multiplicationFactor, Worker* worker)
175 {
176  FrameFilterGradientBase::filterHorizontalVerticalSubFrame<TSource, TTarget, tChannels, tNormalizeByTwo>(source, sourceWidth, sourceHeight, sourcePaddingElements, sourceLeft, sourceTop, target, targetWidth, targetHeight, targetPaddingElements, multiplicationFactor, worker);
177 }
178 
179 template <typename T, typename TIntegral, bool tAbsoluteGradient>
180 void FrameFilterGradient::filterHorizontal1x2LinedIntegralImage(const T* source, const unsigned int width, const unsigned int height, TIntegral* integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements)
181 {
182  static_assert(sizeof(T) <= sizeof(TIntegral), "Invalid integral elements!");
183 
184  ocean_assert(source != nullptr);
185  ocean_assert(width >= 2u);
186  ocean_assert(height >= 1u);
187  ocean_assert(integral != nullptr);
188 
189  /*
190  * This is the resulting lined integral image, with resolution (width)x(height + 1):
191  * ------------
192  * |000000000000|
193  * |0|----------|
194  * |0| |
195  * |0| Integral |
196  * |0| |
197  * |------------
198  */
199 
200  typedef typename DifferenceValueTyper<TIntegral>::Type TSignedIntegral;
201 
202  // entire top line will be set to zero
203  memset(integral, 0x00, width * sizeof(TIntegral));
204 
205 #ifdef OCEAN_DEBUG
206  for (unsigned int n = 0u; n < width; ++n)
207  {
208  ocean_assert(integral[n] == TIntegral(0));
209  }
210 #endif
211 
212  integral += width + integralPaddingElements;
213 
214  // we calculate the first row of the integral image
215 
216  const T* const sourceFirstRowEnd = source + width - 1u; // excluding the last pixel
217  const T* const sourceEnd = source + (width + sourcePaddingElements) * height;
218 
219  const TIntegral* integralPreviousRow = integral;
220 
221  TIntegral previousIntegral = TIntegral(0);
222 
223  *integral++ = TIntegral(0);
224 
225  // the remaining pixels of the first row
226 
227  while (source != sourceFirstRowEnd)
228  {
229  previousIntegral += tAbsoluteGradient ? TIntegral(NumericT<TSignedIntegral>::abs(TSignedIntegral(source[1] - source[0]))) : TIntegral(source[1] - source[0]);
230  ++source;
231 
232  *integral++ = previousIntegral;
233  }
234 
235  source += sourcePaddingElements + 1u; // including the last pixel
236  integral += integralPaddingElements;
237 
238  // we calculate the remaining rows
239 
240  while (source != sourceEnd)
241  {
242  const T* const sourceRowEnd = source + width - 1u; // excluding the last pixel
243 
244  previousIntegral = TIntegral(0);
245 
246  // left pixel
247  *integral++ = TIntegral(0);
248 
249  ++integralPreviousRow;
250 
251  while (source != sourceRowEnd)
252  {
253  previousIntegral += tAbsoluteGradient ? TIntegral(NumericT<TSignedIntegral>::abs(TSignedIntegral(source[1] - source[0]))) : TIntegral(source[1] - source[0]);
254  ++source;
255 
256  *integral++ = previousIntegral + *integralPreviousRow++;
257  }
258 
259  source += sourcePaddingElements + 1u; // including the last pixel
260  integral += integralPaddingElements;
261  integralPreviousRow += integralPaddingElements;
262  }
263 }
264 
265 template <typename T, typename TIntegral, bool tAbsoluteGradient>
266 void FrameFilterGradient::filterVertical2x1LinedIntegralImage(const T* source, const unsigned int width, const unsigned int height, TIntegral* integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements)
267 {
268  ocean_assert(source != nullptr);
269  ocean_assert(width >= 1u);
270  ocean_assert(height >= 2u);
271  ocean_assert(integral != nullptr);
272 
273  const unsigned int sourceStrideElements = width + sourcePaddingElements;
274 
275  /*
276  * This is the resulting lined integral image, with resolution (width + 1)x(height):
277  * ------------
278  * |000000000000|
279  * |0|----------|
280  * |0| |
281  * |0| Integral |
282  * |0| |
283  * |------------
284  */
285 
286  typedef typename DifferenceValueTyper<TIntegral>::Type TSignedIntegral;
287 
288  // entire top line will be set to zero
289  memset(integral, 0x00, (width + 1u) * sizeof(TIntegral));
290 
291 #ifdef OCEAN_DEBUG
292  for (unsigned int n = 0u; n < width + 1u; ++n)
293  {
294  ocean_assert(integral[n] == TIntegral(0));
295  }
296 #endif
297 
298  integral += width + 1u + integralPaddingElements;
299 
300  // we calculate the first row of the integral image
301 
302  const T* const sourceFirstRowEnd = source + width;
303  const T* const sourceEnd = source + sourceStrideElements * (height - 1u); // excluding the last row
304 
305  const TIntegral* integralPreviousRow = integral;
306 
307  TIntegral previousIntegral = TIntegral(0);
308 
309  *integral++ = TIntegral(0);
310 
311  // the remaining pixels of the first row
312 
313  const T* sourceNextRow = source + sourceStrideElements;
314 
315  while (source != sourceFirstRowEnd)
316  {
317  previousIntegral += tAbsoluteGradient ? TIntegral(NumericT<TSignedIntegral>::abs(TSignedIntegral(*sourceNextRow++ - *source++))) : TIntegral(*sourceNextRow++ - *source++);
318 
319  *integral++ = previousIntegral;
320  }
321 
322  source += sourcePaddingElements;
323  sourceNextRow += sourcePaddingElements;
324  integral += integralPaddingElements;
325 
326  // we calculate the remaining rows
327 
328  while (source != sourceEnd)
329  {
330  const T* const sourceRowEnd = source + width;
331 
332  previousIntegral = TIntegral(0);
333 
334  // left pixel
335  *integral++ = TIntegral(0);
336 
337  ++integralPreviousRow;
338 
339  while (source != sourceRowEnd)
340  {
341  previousIntegral += tAbsoluteGradient ? TIntegral(NumericT<TSignedIntegral>::abs(TSignedIntegral(*sourceNextRow++ - *source++))) : TIntegral(*sourceNextRow++ - *source++);
342 
343  *integral++ = previousIntegral + *integralPreviousRow++;
344  }
345 
346  source += sourcePaddingElements;
347  sourceNextRow += sourcePaddingElements;
348 
349  integral += integralPaddingElements;
350  integralPreviousRow += integralPaddingElements;
351  }
352 }
353 
354 }
355 
356 }
357 
358 #endif // META_OCEAN_CV_FRAME_FILTER_GRADIENT_H
This class implements a gradient frame filter.
Definition: FrameFilterGradient.h:27
static void filterHorizontal1x2LinedIntegralImage(const T *source, const unsigned int width, const unsigned int height, TIntegral *integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements)
Determines the lined integral image of the horizontal 1x2 gradient filter when applied to a source im...
Definition: FrameFilterGradient.h:180
static void filterHorizontalVertical(const TSource *source, TTarget *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const TTarget multiplicationFactor=TTarget(1), Worker *worker=nullptr)
Horizontal and vertical gradient filter for a 1-plane frame with arbitrary data type and arbitrary nu...
Definition: FrameFilterGradient.h:162
static void filterHorizontalVerticalSubFrame(const TSource *source, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int sourceLeft, const unsigned int sourceTop, TTarget *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const TTarget multiplicationFactor=TTarget(1), Worker *worker=nullptr)
Horizontal and vertical gradient filter for sub-frame of a 1-plane frame with arbitrary data type and...
Definition: FrameFilterGradient.h:174
static void filterVertical2x1LinedIntegralImage(const T *source, const unsigned int width, const unsigned int height, TIntegral *integral, const unsigned int sourcePaddingElements, const unsigned int integralPaddingElements)
Determines the lined integral image of the vertical 2x1 gradient filter when applied to a source imag...
Definition: FrameFilterGradient.h:266
static void filterHorizontalVerticalMagnitudeSquared(const TSource *source, TTarget *target, const unsigned int width, const unsigned int height, const TTarget multiplicationFactor=TTarget(1), Worker *worker=nullptr)
Squared magnitude gradient filter using the horizontal and vertical gradients that can be applied to ...
Definition: FrameFilterGradient.h:168
T Type
Definition of the data type for the signed difference value.
Definition: DataType.h:176
This class provides basic numeric functionalities.
Definition: Numeric.h:57
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15