Ocean
FrameShrinker.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_SHRINKER_H
9 #define META_OCEAN_CV_FRAME_SHRINKER_H
10 
11 #include "ocean/cv/CV.h"
12 #include "ocean/cv/NEON.h"
13 #include "ocean/cv/SSE.h"
14 
15 #include "ocean/base/Frame.h"
16 #include "ocean/base/Worker.h"
17 
18 #include "ocean/math/Numeric.h"
19 
20 namespace Ocean
21 {
22 
23 namespace CV
24 {
25 
26 /**
27  * This class implements function to downsize a frame.
28  * @ingroup cv
29  */
30 class OCEAN_CV_EXPORT FrameShrinker
31 {
32  protected:
33 
34  /**
35  * Definition of a function pointer allowing to down sample a block of elements by using a 11 pattern.
36  * @param sourceRow0 The upper source row, must be valid
37  * @param sourceRow1 The lower source row, must be valid
38  * @param target The target receiving the down sampled data
39  */
40  typedef void (*DownsampleBlockByTwo8BitPerChannelFunction)(const uint8_t* const sourceRow0, const uint8_t* const sourceRow1, uint8_t* const target);
41 
42  /**
43  * Definition of a function pointer allowing to down sample a binary block of elements by using a 11 pattern.
44  * @param sourceRow0 The upper source row, must be valid
45  * @param sourceRow1 The lower source row, must be valid
46  * @param target The target receiving the down sampled data
47  * @param threshold Minimal sum threshold of four pixels to result in a pixel with value 255
48  */
49  typedef void (*DownsampleBlockByTwoBinary8BitPerChannelFunction)(const uint8_t* const sourceRow0, const uint8_t* const sourceRow1, uint8_t* const target, const uint16_t threshold);
50 
51  public:
52 
53  /**
54  * Reduces the resolution of a given frame by two, applying a 1-1 downsampling.
55  * Each downsampled pixel is based on 2x2 (= four) corresponding pixels from the source image:
56  * <pre>
57  * | 1 1 |
58  * | 1 1 | * 1/4
59  * </pre>
60  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
61  * If the type of the target frame does not match to the input frame the target frame (and image buffer) will be replaced by the correct one.
62  * @param source The source frame to resize, must be valid
63  * @param target The target frame receiving the down sampled frame data, can be invalid
64  * @param worker Optional worker object to distribute the computational load to several CPU cores
65  * @return True, if succeeded
66  */
67  static bool downsampleByTwo11(const Frame& source, Frame& target, Worker* worker = nullptr);
68 
69  /**
70  * Reduces the resolution of a given binary mask by two, applying a 1-1 downsampling.
71  * Each downsampled pixel is based on 2x2 (= four) corresponding pixels from the source image:
72  * <pre>
73  * | 1 1 |
74  * | 1 1 | * 1/4
75  * </pre>
76  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
77  * If the type of the target frame does not match to the input frame the target frame (and image buffer) will be replaced by the correct one.
78  * @param source The source mask to resize, must be valid
79  * @param target The target mask receiving the down sampled frame data, can be invalid
80  * @param threshold The threshold of the minimal sum of the four mask pixels values to result in a downsampled pixel with value 255, with range [0, 255 * 4]
81  * @param worker Optional worker object to distribute the computational load to several CPU cores
82  * @return True, if succeeded
83  */
84  static bool downsampleBinayMaskByTwo11(const Frame& source, Frame& target, const unsigned int threshold = 766u, Worker* worker = nullptr);
85 
86  /**
87  * Reduces the resolution of a given frame by two, applying a 1-4-6-4-1 downsampling.
88  * Each downsampled pixel is based on 5x5 (= 25) corresponding pixels from the source image:
89  * <pre>
90  * | 1 4 6 4 1 |
91  * | 4 16 24 16 4 |
92  * | 6 24 36 24 6 | * 1/256
93  * | 4 16 24 16 4 |
94  * | 1 4 6 4 1 |
95  * </pre>
96  * The filter values are determined at even pixel coordinates (0, 2, 4, ...).
97  * If the type of the target frame does not match to the input frame the target frame (and image buffer) will be replaced by the correct one.<br>
98  * By default, the resolution of the target frame will be set to (source.width() / 2, source.height() / 2).
99  * @param source The source frame to resize, must be valid
100  * @param target The target frame receiving the down sampled frame data, with resolution [source.width() / 2, (source.width() + 1) / 2]x[source.height() / 2, (source.height() + 1) / 2], can be invalid
101  * @param worker Optional worker object to distribute the computational load to several CPU cores
102  * @return True, if succeeded
103  */
104  static bool downsampleByTwo14641(const Frame& source, Frame& target, Worker* worker = nullptr);
105 
106  /**
107  * Reduces the resolution of a given frame by two, taking four pixel values into account.
108  * If the given source image has an odd frame dimension the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
109  * @param frame The frame to down sample, must be valid
110  * @param worker Optional worker object to distribute the computational load to several CPU cores
111  * @return True, if succeeded
112  */
113  static inline bool downsampleByTwo11(Frame& frame, Worker* worker = nullptr);
114 
115  /**
116  * Reduces the resolution of a given binary mask by two, taking 2x2 (= four) mask pixel values into account.
117  * @param mask The mask to down sample, must be valid
118  * @param threshold The threshold of the minimal sum of the four mask pixels values to result in a downsampled pixel with value 255, with range [0, 255 * 4]
119  * @param worker Optional worker object to distribute the computational load to several CPU cores
120  * @return True, if succeeded
121  */
122  static inline bool downsampleBinayMaskByTwo11(Frame& mask, const unsigned int threshold = 766u, Worker* worker = nullptr);
123 
124  /**
125  * Reduces the resolution of a given frame by two, applying a 1-4-6-4-1 downsampling.
126  * Each downsampled pixel is based on 5x5 (= 25) corresponding pixels from the source image:
127  * <pre>
128  * | 1 4 6 4 1 |
129  * | 4 16 24 16 4 |
130  * | 6 24 36 24 6 | * 1/256
131  * | 4 16 24 16 4 |
132  * | 1 4 6 4 1 |
133  * </pre>
134  * The filter values are determined at even pixel coordinates (0, 2, 4, ...).<br>
135  * The resulting frame will have the resolution (frame.width() / 2, frame.height() / 2).
136  * @param frame The frame to down sample, must be valid
137  * @param worker Optional worker object to distribute the computational load to several CPU cores
138  * @return True, if succeeded
139  */
140  static inline bool downsampleByTwo14641(Frame& frame, Worker* worker = nullptr);
141 
142  /**
143  * Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8.
144  * @param source The source frame buffer to be used, must be valid
145  * @param pyramidTarget The frame buffer of the frame pyramid, large enough for the requested layers, must be valid
146  * @param pyramidTargetSize The size of the pyramid target memory, in bytes, with range [1, infinity)
147  * @param layers The number of pyramid layers to be created, with range [1, infinity)
148  * @param copyFirstLayer True, to copy the first layer before processing the next finer layers; False, to start directly with the next coarser layer (the memory for pyramidTarget can then be correspondingly smaller)
149  * @param worker Optional worker object to distribute the computational load, nullptr otherwise
150  * @return True, if succeeded
151  */
152  static bool pyramidByTwo11(const Frame& source, uint8_t* const pyramidTarget, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, Worker* worker);
153 
154  /**
155  * Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8 applying a 1-1 downsampling.
156  * Each pixel of a coarser pyramid level is based on 2x2 pixels from the corresponding finer pyramid level.
157  * @param source The source frame buffer to be used, must be valid
158  * @param pyramidTarget The frame buffer of the frame pyramid, large enough for the requested layers, must be valid
159  * @param sourceWidth Width of the source frame in pixel, with range [1, infinity)
160  * @param sourceHeight Height of the source frame in pixel, with range [1, infinity)
161  * @param channels The number of data channel the frames have, with range [1, infinity)
162  * @param pyramidTargetSize The size of the pyramid target memory, in bytes, with range [1, infinity)
163  * @param layers The number of pyramid layers to be created, with range [1, infinity)
164  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
165  * @param copyFirstLayer True, to copy the first layer before processing the next finer layers; False, to start directly with the next coarser layer (the memory for pyramidTarget can then be correspondingly smaller)
166  * @param worker Optional worker object to distribute the computational load, nullptr otherwise
167  * @return True, if succeeded
168  */
169  static bool pyramidByTwo8BitPerChannel11(const uint8_t* source, uint8_t* pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const unsigned int sourcePaddingElements, const bool copyFirstLayer, Worker* worker);
170 
171  /**
172  * Reduces the resolution of a given frame by two, applying a 1-1 downsampling.
173  * Each downsampled pixel is based on 2x2 (= four) corresponding pixels from the source image:
174  * <pre>
175  * | 1 1 |
176  * | 1 1 | * 1/4
177  * </pre>
178  * The target width and target height will be sourceWidth / 2, targetHeight / 2.<br>
179  * In case, the given source image has an odd frame resolution the last pixel row or the last pixel column is filtered together with the two valid rows or columns respectively.<br>
180  * However, in general, this function is meant to be used for images with even width and height.
181  * @param source The source frame buffer to resize, must be valid
182  * @param target The target frame buffer receiving the down sampled image information, must be valid
183  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
184  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
185  * @param channels The number of data channel the frames have, with range [1, infinity)
186  * @param sourcePaddingElements Optional padding at the end of each source row in elements, with range [0, infinity)
187  * @param targetPaddingElements Optional padding at the end of each target row in elements, with range [0, infinity)
188  * @param worker Optional worker object to distribute the computational load to several CPU cores
189  */
190  static inline void downsampleByTwo8BitPerChannel11(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
191 
192  /**
193  * Reduces the resolution of a given binary frame with 8bit per pixel with values 0 and 255 by two, taking four pixel values into account.
194  * @param source Binary source frame buffer to resize
195  * @param target Binary target frame buffer
196  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
197  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
198  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
199  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
200  * @param threshold Minimal sum threshold of four pixels to result in a pixel with value 255
201  * @param worker Optional worker object to distribute the computational load to several CPU cores
202  */
203  static inline void downsampleBinayMaskByTwo8BitPerChannel11(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int threshold = 766u, Worker* worker = nullptr);
204 
205  /**
206  * Reduces the resolution of a given frame by two, applying a 1-4-6-4-1 downsampling.
207  * Each downsampled pixel is based on 5x5 (= 25) corresponding pixels from the source image:
208  * <pre>
209  * | 1 4 6 4 1 |
210  * | 4 16 24 16 4 |
211  * | 6 24 36 24 6 | * 1/256
212  * | 4 16 24 16 4 |
213  * | 1 4 6 4 1 |
214  * </pre>
215  * The filter values are determined at even pixel coordinates.
216  * @param source The source frame to resize, must be valid
217  * @param target The target frame receiving the down sampled frame data, with memory for (targetWidth * targetHeight) pixels, must be valid
218  * @param sourceWidth The width of the source frame in pixel, with range [2, infinity)
219  * @param sourceHeight The height of the source frame in pixel, with range [2, infinity)
220  * @param targetWidth The width of the target frame in pixel, with range [sourceWidth / 2, (sourceWidth + 1) / 2]
221  * @param targetHeight The height of the target frame in pixel, with range [sourceHeight / 2, (sourceHeight + 1) / 2]
222  * @param channels The number of frame channels, with range [1, infinity)
223  * @param sourcePaddingElements Optional padding at the end of each source row in elements, with range [0, infinity)
224  * @param targetPaddingElements Optional padding at the end of each target row in elements, with range [0, infinity)
225  * @param worker Optional worker object to distribute the computational load to several CPU cores
226  */
227  static inline void downsampleByTwo8BitPerChannel14641(const uint8_t* const source, uint8_t* const target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
228 
229  protected:
230 
231  /**
232  * Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8.
233  * @param source The source frame buffer from which the pyramid will be created, must be valid
234  * @param pyramidTarget The frame buffer of the frame pyramid, large enough for the requested layers, must be valid
235  * @param sourceWidth Width of the source frame in pixel, with range [1, infinity)
236  * @param sourceHeight Height of the source frame in pixel, with range [1, infinity)
237  * @param channels The number of frame channels the source frame has, with range [1, infinity)
238  * @param pyramidTargetSize The size of the pyramid target memory, in bytes, with range [1, infinity)
239  * @param layers The number of pyramid layers to be created, with range [1, infinity)
240  * @param copyFirstLayer True, to copy the first layer before processing the next finer layers; False, to start directly with the next coarser layer
241  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
242  * @param worker Optional worker object to distribute the computational load
243  * @param threads The number of threads to be used if a valid worker is defined, with range [1u, worker->threads()] and the following must hold: threads * 2^layers <= sourceHeight
244  * @return True, if succeeded
245  */
246  static bool pyramidByTwo8BitPerChannel11WithThreads(const uint8_t* source, uint8_t* pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, const unsigned int sourcePaddingElements, const unsigned int threads, Worker* worker);
247 
248  /**
249  * Fills a subset of the buffer of a pyramid frame for a given frame with 1 plane and data type DT_UNSIGNED_INTEGER_8.
250  * @param source The source frame buffer from which the pyramid will be created, must be valid
251  * @param pyramidTarget The frame buffer of the frame pyramid, large enough for the requested layers, must be valid
252  * @param sourceWidth Width of the source frame in pixel, with range [1, infinity)
253  * @param sourceHeight Height of the source frame in pixel, with range [1, infinity)
254  * @param channels The number of frame channels the source image has, with range [1, infinity)
255  * @param pyramidTargetSize The size of the pyramid target memory, in bytes, with range [1, infinity)
256  * @param layers The number of pyramid layers to be created, with range [1, infinity)
257  * @param copyFirstLayer True, to copy the first layer before processing the next finer layers; False, to start directly with the next coarser layer
258  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
259  * @param firstSubsetsSourceHeight The height of the first subsets on the finest pyramid layer, with range [1, sourceHeight]
260  * @param subsets The number of subsets which will be used in parallel (the number of threads executing the function in parallel)
261  * @param subsetIndex The index of the subset which is handled, with range [0, subsetIndex)
262  * @param valueOne The parameter must be 1
263  */
264  static void pyramidByTwo8BitPerChannel11WithThreadsSubset(const uint8_t* source, uint8_t* pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, const unsigned int sourcePaddingElements, const unsigned int firstSubsetsSourceHeight, const unsigned int subsets, const unsigned int subsetIndex, const unsigned int valueOne);
265 
266  /**
267  * Reduces the resolution of a given frame by two.
268  * @param source The source frame buffer to resize, must be valid
269  * @param target The target frame buffer receiving the down sampled image information, must be valid
270  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
271  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
272  * @param channels The number of data channel the frames have, with range [1, infinity)
273  * @param sourcePaddingElements Optional padding at the end of each source row in elements, with range [0, infinity)
274  * @param targetPaddingElements Optional padding at the end of each target row in elements, with range [0, infinity)
275  * @param firstTargetRow The first target row to be handled, with range [0, sourceHeight / 2 - 1]
276  * @param numberTargetRows The number of target rows to be handled, with range [1, sourceHeight / 2 - firstTargetRow]
277  */
278  static void downsampleByTwo8BitPerChannel11Subset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
279 
280  /**
281  * Reduces the resolution of a given binary frame with 8bit per pixel with values 0 and 255 by two, taking four pixel values into account.
282  * @param source The binary source frame, must be valid
283  * @param target The binary target frame, must be valid
284  * @param sourceWidth Width of the source frame in pixel, with range [2, infinity)
285  * @param sourceHeight Height of the source frame in pixel, with range [2, infinity)
286  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
287  * @param targetPaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
288  * @param threshold The threshold of the minimal sum of the four mask pixels values to result in a downsampled pixel with value 255, with range [0, 255 * 4]
289  * @param firstTargetRow The first target row to be handled, with range [0, sourceHeight / 2 - 1]
290  * @param numberTargetRows The number of target rows to be handled, with range [1, sourceHeight / 2 - firstTargetRow]
291  */
292  static void downsampleBinayMaskByTwo8BitPerChannel11Subset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int threshold, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
293 
294  /**
295  * Determines the function to down sample a block of pixel elements by two with a 11 filter pattern.
296  * This function will return the function able to handle the largest block of elements, if any function exists.
297  * @param sourceWidth The width of the source frame in pixel, with range [2, infinity)
298  * @param channels The number of frame channels, with range [1, infinity)
299  * @param downsampleBlockFunction The resulting function down sampling the block of elements, nullptr if no matching function could be determined
300  * @param sourceElementsPerBlock The resulting number of source elements which will be handled by the resulting down sampling function, 0 if no matching function could be determined
301  */
302  static void determineFunctionDownsampleBlockByTwo8Bit11(const unsigned int sourceWidth, const unsigned int channels, DownsampleBlockByTwo8BitPerChannelFunction& downsampleBlockFunction, unsigned int& sourceElementsPerBlock);
303 
304  /**
305  * Downsamples an area of 2x3 pixels (two rows and three columns) to one pixel in a frame, applying a 1-2-1 down sampling filter.
306  * This function is typically handling the last pixel in a frame (if the frame has an odd width).
307  * @param source The location of the top left pixel in the source frame, must be valid
308  * @param target The location in the target frame, must be valid
309  * @param channels The number of channels the source (and target) frame have, with range [1, infinity)
310  * @param sourceStrideElements The number of elements between two successive rows in the source frame, in elements, with range [sourceWidth * channels, infinity)
311  */
312  OCEAN_PREVENT_INLINE static void downsampleByTwoOneRowThreeColumns8BitPerChannel121(const uint8_t* source, uint8_t* target, const unsigned int channels, const unsigned int sourceStrideElements);
313 
314  /**
315  * Downsamples three rows to one row in a frame, applying a 2x3 [1-2-1, 1-2-1] down sampling filter.
316  * In case the width of the source rows is 1 pixel, a 1x3 [1-2-1] is applied.<br>
317  * In case the width of the source rows is not a multiple of two, a 3x3 [1-2-1, 2-4-2, 1-2-1] filter is applied to the last 3 pixels.
318  * @param source The location of the left pixel in the top source row, must be valid
319  * @param target The location in the left pixel target row, must be valid
320  * @param sourceWidth The number of pixels in the source frame, with range [1, infinity)
321  * @param channels The number of channels the source (and target) frame have, with range [1, infinity)
322  * @param sourceStrideElements The number of elements between two successive rows in the source frame, in elements, with range [sourceWidth * channels, infinity)
323  */
324  OCEAN_PREVENT_INLINE static void downsampleByTwoThreeRows8BitPerChannel121(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int channels, const unsigned int sourceStrideElements);
325 
326  /**
327  * Applies a vertical 14641 filter to each pixel in a given row not applying any SIMD instructions.
328  * This function can be used to down sample an image e.g., by a factor of two.
329  * @param source The entire source frame holding the row to which the filter is applied, must be valid
330  * @param targetRow The target row receiving the filter results which are not normalized, must be valid
331  * @param sourceElements The number of elements in each row (pixels * channels), with range [1, infinity)
332  * @param sourceHeight The height of the source frame in pixel, with range [2, infinity)
333  * @param sourceStrideElements The stride of the source frame (the number of elements in each row - may including padding at the end of each row), with range [sourceElements, infinity)
334  * @param ySource The row within the source frame to which the filter will be applied, with range [0, sourceHeight)
335  * @see downsampleByTwoRowHorizontal8BitPerChannel14641().
336  */
337  static void downsampleByTwoRowVertical8BitPerChannel14641(const uint8_t* const source, uint16_t* targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource);
338 
339  /**
340  * Applies a horizontal 14641 filter to each second pixel in a given row not applying any SIMD instructions.
341  * Each second pixel is skipped so that the target row has a length half of the source row.<br>
342  * This function can be used to down sample an image e.g., by a factor of two.
343  * @param sourceRow The source row already holding the vertical filter responses to which now the horizontal filter will be applied, must be valid
344  * @param targetRow The target row receiving the filter results which will be normalized before assignment, must be valid
345  * @param targetWidth The width of the target row in pixel, with range [1, infinity)
346  * @param channels The number of channels the target row (and source row) has, with range [1, infinity)
347  * @see downsampleByTwoRowVertical8BitPerChannel14641().
348  */
349  static void downsampleByTwoRowHorizontal8BitPerChannel14641(const uint16_t* sourceRow, uint8_t* targetRow, const unsigned int targetWidth, const unsigned int channels);
350 
351 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
352 
353  /**
354  * Applies a vertical 14641 filter to each pixel in a given row using SSE instructions.
355  * This function can be used to down sample an image e.g., by a factor of two.
356  * @param source The entire source frame holding the row to which the filter is applied, must be valid
357  * @param targetRow The target row receiving the filter results which are not normalized, must be valid
358  * @param sourceElements The number of elements in each row (pixels * channels), with range [1, infinity)
359  * @param sourceHeight The height of the source frame in pixel, with range [2, infinity)
360  * @param sourceStrideElements The stride of the source frame (the number of elements in each row - may including padding at the end of each row), with range [sourceElements, infinity)
361  * @param ySource The row within the source frame to which the filter will be applied, with range [0, sourceHeight)
362  * @see downsampleByTwoRowHorizontal8BitPerChannel14641NEON().
363  */
364  static void downsampleByTwoRowVertical8BitPerChannel14641SSE(const uint8_t* const source, uint16_t* targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource);
365 
366 #endif // OCEAN_HARDWARE_SSE_VERSION >= 41
367 
368 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
369 
370  /**
371  * Applies a vertical 14641 filter to each pixel in a given row using NEON instructions.
372  * This function can be used to down sample an image e.g., by a factor of two.
373  * @param source The entire source frame holding the row to which the filter is applied, must be valid
374  * @param targetRow The target row receiving the filter results which are not normalized, must be valid
375  * @param sourceElements The number of elements in each row (pixels * channels), with range [16, infinity)
376  * @param sourceHeight The height of the source frame in pixel, with range [2, infinity)
377  * @param sourceStrideElements The stride of the source frame (the number of elements in each row - may including padding at the end of each row), with range [sourceElements, infinity)
378  * @param ySource The row within the source frame to which the filter will be applied, with range [0, sourceHeight)
379  * @see downsampleByTwoRowHorizontal8BitPerChannel14641NEON().
380  */
381  static void downsampleByTwoRowVertical8BitPerChannel14641NEON(const uint8_t* const source, uint16_t* targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource);
382 
383  /**
384  * Applies a horizontal 14641 filter to each second pixel in a given row applying NEON instructions.
385  * Each second pixel is skipped so that the target row has a length half of the source row.<br>
386  * This function can be used to down sample an image e.g., by a factor of two.
387  * @param sourceRow The source row already holding the vertical filter responses to which now the horizontal filter will be applied, must be valid
388  * @param targetRow The target row receiving the filter results which will be normalized before assignment, must be valid
389  * @param targetWidth The width of the target row in pixel, with individual ranges depending on tChannels
390  * @param channels The number of frame channels the target row (and source row) has, with range [1, infinity)
391  * @see downsampleByTwoRowVertical8BitPerChannel14641NEON().
392  * @tparam tChannels The number of channels the target row (and source row) has, with range [1, 4]
393  */
394  template <unsigned int tChannels>
395  static void downsampleByTwoRowHorizontal8BitPerChannel14641NEON(const uint16_t* sourceRow, uint8_t* targetRow, const unsigned int targetWidth, const unsigned int channels);
396 
397 #endif // OCEAN_HARDWARE_NEON_VERSION >= 10
398 
399  /**
400  * Reduces the resolution in a subregion of a given frame by two, taking 5x5 (= 25) pixel values into account.
401  * The filter values are determined at even pixel coordinates.
402  * @param source The source frame to resize, must be valid
403  * @param target The target frame receiving the down sample frame data, with memory for (targetWidth * targetHeight) pixels, must be valid
404  * @param sourceWidth The width of the source frame in pixel, with range [2, infinity)
405  * @param sourceHeight The height of the source frame in pixel, with range [2, infinity)
406  * @param targetWidth The width of the target frame in pixel, with range [sourceWidth / 2, (sourceWidth + 1) / 2]
407  * @param channels The number of frame channels, with range [1, infinity)
408  * @param sourceStrideElements The stride of the source frame in elements (sourceWidth * channels + optional padding), with range [sourceWidth * channels, infinity)
409  * @param targetStrideElements The stride of the target frame in elements (targetWidth * channels + optional padding), with range [targetWidth * channels, infinity)
410  * @param firstTargetRow The first target row to be handled, with range [0, targetHeight)
411  * @param numberTargetRows The number of target rows to be handled, with range [1, targetHeight - firstTargetRow]
412  */
413  static void downsampleByTwo8BitPerChannel14641Subset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int channels, const unsigned int sourceStrideElements, const unsigned int targetStrideElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
414 
415  /**
416  * Mirrors a given value at the left border if necessary.
417  * The function provides a result as below:<br>
418  * <pre>
419  * Original: -3 -2 -1 | 0 1 2 3 4 5 6
420  * Result: 2 1 0 | 0 1 2 3 4 5 6
421  * </pre>
422  * @param value The value to be mirrored, with range (-infinity, infinity)
423  * @return Mirrored value
424  * @ingroup base
425  */
426  static inline unsigned int mirroredBorderLocationLeft(const int value);
427 
428  /**
429  * Mirrors a given value at the right border if necessary.
430  * The values is mirrored according to a given size parameter.<br>
431  * The function provides a result as below:<br>
432  * <pre>
433  * Original: 4 5 6 ... s-2 s-1 | s s+1 s+2
434  * Result: 4 5 6 ... s-2 s-1 | s-1 s-2 s-3
435  * </pre>
436  * @param value The value to be mirrored, with range [0, 2*size)
437  * @param size Specified size defining the upper mirror border, with range [1, 2147483647]
438  * @return Mirrored value
439  * @ingroup base
440  */
441  static inline unsigned int mirroredBorderLocationRight(const unsigned int value, const unsigned int size);
442 };
443 
444 inline bool FrameShrinker::downsampleByTwo11(Frame& frame, Worker* worker)
445 {
446  Frame tmpFrame;
447  if (!downsampleByTwo11(frame, tmpFrame, worker))
448  {
449  return false;
450  }
451 
452  tmpFrame.setTimestamp(frame.timestamp());
453  tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
454 
455  frame = std::move(tmpFrame);
456  return true;
457 }
458 
459 inline bool FrameShrinker::downsampleBinayMaskByTwo11(Frame& mask, const unsigned int threshold, Worker* worker)
460 {
461  Frame tmpMask;
462  if (!downsampleBinayMaskByTwo11(mask, tmpMask, threshold, worker))
463  {
464  return false;
465  }
466 
467  tmpMask.setTimestamp(mask.timestamp());
468  tmpMask.setRelativeTimestamp(mask.relativeTimestamp());
469 
470  mask = std::move(tmpMask);
471  return true;
472 }
473 
475 {
476  Frame tmpFrame;
477  if (!downsampleByTwo14641(frame, tmpFrame, worker))
478  {
479  return false;
480  }
481 
482  tmpFrame.setTimestamp(frame.timestamp());
483  tmpFrame.setRelativeTimestamp(frame.relativeTimestamp());
484 
485  frame = std::move(tmpFrame);
486  return true;
487 }
488 
489 inline void FrameShrinker::downsampleBinayMaskByTwo8BitPerChannel11(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int threshold, Worker* worker)
490 {
491  ocean_assert(source != nullptr && target != nullptr);
492  ocean_assert(sourceWidth >= 2u && sourceHeight >= 2u);
493  ocean_assert(threshold <= 255 * 4u);
494 
495  const unsigned int targetHeight = sourceHeight / 2u;
496  ocean_assert(targetHeight > 0u);
497 
498  if (worker)
499  {
500  worker->executeFunction(Worker::Function::createStatic(&downsampleBinayMaskByTwo8BitPerChannel11Subset, source, target, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements, threshold, 0u, 0u), 0u, targetHeight, 7u, 8u, 20u);
501  }
502  else
503  {
504  downsampleBinayMaskByTwo8BitPerChannel11Subset(source, target, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements, threshold, 0u, targetHeight);
505  }
506 }
507 
508 inline void FrameShrinker::downsampleByTwo8BitPerChannel11(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
509 {
510  ocean_assert(source != nullptr && target != nullptr);
511  ocean_assert(sourceWidth >= 2u && sourceHeight >= 1u);
512  ocean_assert(channels >= 1u);
513 
514  const unsigned int targetHeight = sourceHeight / 2u;
515 
516  if (worker)
517  {
518  worker->executeFunction(Worker::Function::createStatic(FrameShrinker::downsampleByTwo8BitPerChannel11Subset, source, target, sourceWidth, sourceHeight, channels, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, targetHeight);
519  }
520  else
521  {
522  downsampleByTwo8BitPerChannel11Subset(source, target, sourceWidth, sourceHeight, channels, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
523  }
524 }
525 
526 inline unsigned int FrameShrinker::mirroredBorderLocationLeft(const int value)
527 {
528  // Outside | Inside
529  // Original: -3 -2 -1 | 0 1 2 3 4 5 6
530  // Result: 2 1 0 | 0 1 2 3 4 5 6
531 
532  if (value >= 0)
533  {
534  return value;
535  }
536  else
537  {
538  return -value - 1;
539  }
540 }
541 
542 inline unsigned int FrameShrinker::mirroredBorderLocationRight(const unsigned int value, const unsigned int size)
543 {
544  ocean_assert(value < 2u * size);
545 
546  // Inside | Outside
547  // Original: 4 5 6 ... s-2 s-1 | s s+1 s+2
548  // Result: 4 5 6 ... s-2 s-1 | s-1 s-2 s-3
549 
550  if (value < size)
551  {
552  return value;
553  }
554  else
555  {
556  ocean_assert(size * 2u - value - 1u < size);
557  return size * 2u - value - 1u;
558  }
559 }
560 
561 inline void FrameShrinker::downsampleByTwo8BitPerChannel14641(const uint8_t* const source, uint8_t* const target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
562 {
563  ocean_assert(source != nullptr && target != nullptr);
564  ocean_assert(sourceWidth >= 2u && sourceHeight >= 2u);
565  ocean_assert((sourceWidth + 0u) / 2u == targetWidth || (sourceWidth + 1u) / 2u == targetWidth);
566  ocean_assert((sourceHeight + 0u) / 2u == targetHeight || (sourceHeight + 1u) / 2u == targetHeight);
567  ocean_assert(channels != 0u);
568 
569  const unsigned int sourceStrideElements = sourceWidth * channels + sourcePaddingElements;
570  const unsigned int targetStrideElements = targetWidth * channels + targetPaddingElements;
571 
572  if (worker)
573  {
574  worker->executeFunction(Worker::Function::createStatic(downsampleByTwo8BitPerChannel14641Subset, source, target, sourceWidth, sourceHeight, targetWidth, channels, sourceStrideElements, targetStrideElements, 0u, 0u), 0u, targetHeight);
575  }
576  else
577  {
578  downsampleByTwo8BitPerChannel14641Subset(source, target, sourceWidth, sourceHeight, targetWidth, channels, sourceStrideElements, targetStrideElements, 0u, targetHeight);
579  }
580 }
581 
582 }
583 
584 }
585 
586 #endif // META_OCEAN_CV_FRAME_SHRINKER_H
This class implements function to downsize a frame.
Definition: FrameShrinker.h:31
static void downsampleBinayMaskByTwo8BitPerChannel11Subset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int threshold, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Reduces the resolution of a given binary frame with 8bit per pixel with values 0 and 255 by two,...
static void downsampleByTwoRowVertical8BitPerChannel14641(const uint8_t *const source, uint16_t *targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource)
Applies a vertical 14641 filter to each pixel in a given row not applying any SIMD instructions.
static bool pyramidByTwo8BitPerChannel11(const uint8_t *source, uint8_t *pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const unsigned int sourcePaddingElements, const bool copyFirstLayer, Worker *worker)
Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8 apply...
static void downsampleByTwoRowVertical8BitPerChannel14641SSE(const uint8_t *const source, uint16_t *targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource)
Applies a vertical 14641 filter to each pixel in a given row using SSE instructions.
static void downsampleBinayMaskByTwo8BitPerChannel11(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int threshold=766u, Worker *worker=nullptr)
Reduces the resolution of a given binary frame with 8bit per pixel with values 0 and 255 by two,...
Definition: FrameShrinker.h:489
static bool pyramidByTwo8BitPerChannel11WithThreads(const uint8_t *source, uint8_t *pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, const unsigned int sourcePaddingElements, const unsigned int threads, Worker *worker)
Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8.
static void downsampleByTwo8BitPerChannel11(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Reduces the resolution of a given frame by two, applying a 1-1 downsampling.
Definition: FrameShrinker.h:508
static void downsampleByTwo8BitPerChannel11Subset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Reduces the resolution of a given frame by two.
static OCEAN_PREVENT_INLINE void downsampleByTwoThreeRows8BitPerChannel121(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int channels, const unsigned int sourceStrideElements)
Downsamples three rows to one row in a frame, applying a 2x3 [1-2-1, 1-2-1] down sampling filter.
static void downsampleByTwo8BitPerChannel14641(const uint8_t *const source, uint8_t *const target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int channels, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Reduces the resolution of a given frame by two, applying a 1-4-6-4-1 downsampling.
Definition: FrameShrinker.h:561
static void downsampleByTwoRowHorizontal8BitPerChannel14641(const uint16_t *sourceRow, uint8_t *targetRow, const unsigned int targetWidth, const unsigned int channels)
Applies a horizontal 14641 filter to each second pixel in a given row not applying any SIMD instructi...
static void pyramidByTwo8BitPerChannel11WithThreadsSubset(const uint8_t *source, uint8_t *pyramidTarget, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int channels, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, const unsigned int sourcePaddingElements, const unsigned int firstSubsetsSourceHeight, const unsigned int subsets, const unsigned int subsetIndex, const unsigned int valueOne)
Fills a subset of the buffer of a pyramid frame for a given frame with 1 plane and data type DT_UNSIG...
static bool downsampleByTwo11(const Frame &source, Frame &target, Worker *worker=nullptr)
Reduces the resolution of a given frame by two, applying a 1-1 downsampling.
static OCEAN_PREVENT_INLINE void downsampleByTwoOneRowThreeColumns8BitPerChannel121(const uint8_t *source, uint8_t *target, const unsigned int channels, const unsigned int sourceStrideElements)
Downsamples an area of 2x3 pixels (two rows and three columns) to one pixel in a frame,...
static bool pyramidByTwo11(const Frame &source, uint8_t *const pyramidTarget, const size_t pyramidTargetSize, const unsigned int layers, const bool copyFirstLayer, Worker *worker)
Fills the buffer of a pyramid frame for frames with 1 plane and data type DT_UNSIGNED_INTEGER_8.
static bool downsampleBinayMaskByTwo11(const Frame &source, Frame &target, const unsigned int threshold=766u, Worker *worker=nullptr)
Reduces the resolution of a given binary mask by two, applying a 1-1 downsampling.
static void downsampleByTwoRowVertical8BitPerChannel14641NEON(const uint8_t *const source, uint16_t *targetRow, const unsigned int sourceElements, const unsigned int sourceHeight, const unsigned int sourceStrideElements, const unsigned int ySource)
Applies a vertical 14641 filter to each pixel in a given row using NEON instructions.
static void downsampleByTwoRowHorizontal8BitPerChannel14641NEON(const uint16_t *sourceRow, uint8_t *targetRow, const unsigned int targetWidth, const unsigned int channels)
Applies a horizontal 14641 filter to each second pixel in a given row applying NEON instructions.
static void downsampleByTwo8BitPerChannel14641Subset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int channels, const unsigned int sourceStrideElements, const unsigned int targetStrideElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Reduces the resolution in a subregion of a given frame by two, taking 5x5 (= 25) pixel values into ac...
static bool downsampleByTwo14641(const Frame &source, Frame &target, Worker *worker=nullptr)
Reduces the resolution of a given frame by two, applying a 1-4-6-4-1 downsampling.
static void determineFunctionDownsampleBlockByTwo8Bit11(const unsigned int sourceWidth, const unsigned int channels, DownsampleBlockByTwo8BitPerChannelFunction &downsampleBlockFunction, unsigned int &sourceElementsPerBlock)
Determines the function to down sample a block of pixel elements by two with a 11 filter pattern.
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 Ocean's image class.
Definition: Frame.h:1760
void setRelativeTimestamp(const Timestamp &relative)
Sets the relative timestamp of this frame.
Definition: Frame.h:4121
void setTimestamp(const Timestamp &timestamp)
Sets the timestamp of this frame.
Definition: Frame.h:4116
const Timestamp & timestamp() const
Returns the timestamp of this frame.
Definition: Frame.h:4106
const Timestamp & relativeTimestamp() const
Returns the relative timestamp of this frame.
Definition: Frame.h:4111
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.
static unsigned int mirroredBorderLocationRight(const unsigned int value, const unsigned int size)
Mirrors a given value at the right border if necessary.
Definition: FrameShrinker.h:542
static unsigned int mirroredBorderLocationLeft(const int value)
Mirrors a given value at the left border if necessary.
Definition: FrameShrinker.h:526
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15