Ocean
AdvancedFrameInterpolatorBilinear.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_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_H
9 #define META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_H
10 
15 
16 #include "ocean/base/DataType.h"
17 #include "ocean/base/Frame.h"
18 #include "ocean/base/Utilities.h"
19 #include "ocean/base/Worker.h"
20 
24 
27 
29 #include "ocean/math/Triangle2.h"
30 #include "ocean/math/Vector2.h"
31 #include "ocean/math/Vector3.h"
32 
33 namespace Ocean
34 {
35 
36 namespace CV
37 {
38 
39 namespace Advanced
40 {
41 
42 /**
43  * This class implements an advanced bilinear frame interpolator.
44  * @ingroup cvadvanced
45  */
46 class OCEAN_CV_ADVANCED_EXPORT AdvancedFrameInterpolatorBilinear
47 {
48  public:
49 
50  /**
51  * The following comfort class provides comfortable functions simplifying prototyping applications but also increasing binary size of the resulting applications.
52  * Best practice is to avoid using these functions if binary size matters,<br>
53  * as for every comfort function a corresponding function exists with specialized functionality not increasing binary size significantly.<br>
54  */
55  class OCEAN_CV_ADVANCED_EXPORT Comfort
56  {
57  public:
58 
59  /**
60  * Transforms a given input frame into an output frame (with arbitrary frame dimension) by application of a homography.
61  * The output frame must have the same pixel format and pixel origin as the input frame, however the dimension of the output frame can be arbitrary.<br>
62  * Further, this function uses a filter mask for output pixels, only valid output mask pixels will be interpolated.<br>
63  * In case the input position lies outside the input frame's domain, the position will be clamped to ensure a valid interpolation result for each pixel with valid filter mask.<br>
64  * The frame must have a 1-plane pixel format with DT_UNSIGNED_INTEGER_8 as data type (e.g., FORMAT_Y8, FORMAT_RGB24, FORMAT_RGBA32, ...).
65  * @param input The input frame that will be transformed, must be valid
66  * @param outputFilterMask The filter mask for the output image, with same resolution as the output frame, must be valid
67  * @param output The Output frame resulting by application of the given homography, with same pixel format and pixel origin as the input frame, must have a valid dimension
68  * @param input_H_output Homography used to transform the given input frame by following equation: inputPoint = input_H_output * outputPoint, must be valid
69  * @param outputBoundingBox Optional bounding box to apply the interpolation to a subset of the output frame only, invalid to handle the entire output frame
70  * @param worker Optional worker object to distribute the computational load
71  * @return True, if succeeded
72  */
73  static bool homographyFilterMask(const Frame& input, const Frame& outputFilterMask, Frame& output, const SquareMatrix3& input_H_output, const PixelBoundingBox& outputBoundingBox = PixelBoundingBox(), Worker* worker = nullptr);
74 
75  /**
76  * Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame which has a corresponding mask frame specifying valid and invalid pixels in the frame.
77  * This function allows an interpolation position outside the frame due to the resulting mask value.<br>
78  * This function uses an integer interpolation with a precision of 1/128.
79  * @param frame The frame to determine the pixel values from, must be valid
80  * @param mask The mask frame specifying valid and invalid frame pixels, must be valid
81  * @param channels Number of channels of the given frame, with range [1, 8]
82  * @param width The width of the frame (and mask) in pixel, with range [1, infinity)
83  * @param height The height of the frame (and mask) in pixel, with range [1, infinity)
84  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
85  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
86  * @param pixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
87  * @param position The position for which the interpolated pixel will be determined, with ranges (-infinity, infinity)x(-infinity, infinity), for PC_TOP_LEFT and PC_CENTER
88  * @param result Resulting pixel values, must be valid, must be valid
89  * @param resultMask The resulting mask value, must be valid
90  * @param maskValue The 8 bit mask value for valid pixels, an invalid pixel is defined by 0xFF - maskValue
91  * @return True, if succeeded
92  * @tparam TScalar The scalar data type of the sub-pixel position
93  */
94  template <typename TScalar = Scalar>
95  static inline bool interpolatePixelWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelCenter pixelCenter, const VectorT2<TScalar>& position, uint8_t* result, uint8_t& resultMask, const uint8_t maskValue = 0xFFu);
96  };
97 
98  public:
99 
100  /**
101  * Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
102  * @param frame The image in which the interpolated patch is located, must be valid
103  * @param width The width of the image, in pixel, with range [patchWidth + 1, infinity)
104  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
105  * @param buffer The target buffer with `tChannels * patchWidth * patchHeight` elements, must be valid
106  * @param position The center position of the patch in the image, with range [patchWidth/2, width - patchWidth/2 - 1)x[patchHeight/2, height - patchHeight/2 - 1) for PC_TOP_LEFT, [0.5 + patchWidth/2, width - patchWidth/2 - 0.5)x[0.5 + patchHeight/2, height - patchHeight/2 - 0.5) for PC_CENTER
107  * @param patchWidth The width of the image patch in pixel, with range [1, infinity), must be odd
108  * @param patchHeight The height of the image patch in pixel, with range [1, infinity), must be odd
109  * @tparam tChannels The number of frame channels, with range [1, infinity)
110  * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
111  * @tparam TScalar The scalar data type of the sub-pixel position
112  */
113  template <unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
114  static inline void interpolatePatch8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t* const buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight);
115 
116  /**
117  * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
118  * @param frame The image in which the interpolated patch is located, must be valid
119  * @param width The width of the image, in pixel, with range [tPatchSize + 1, infinity)
120  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
121  * @param buffer The target buffer with `tChannels * tPatchSize * tPatchSize` elements, must be valid
122  * @param position The center position of the square region in the image, with range [tPatchSize/2, width - tPatchSize/2 - 1)x[tPatchSize/2, height - tPatchSize/2 - 1) for PC_TOP_LEFT, [tPatchSize/2, width - tPatchSize/2]x[tPatchSize/2, height - tPatchSize/2] for PC_CENTER
123  * @tparam tChannels The number of frame channels, with range [1, infinity)
124  * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
125  * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
126  */
127  template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter = PC_TOP_LEFT>
128  static inline void interpolateSquarePatch8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t* const buffer, const Vector2& position);
129 
130  /**
131  * Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
132  * An additional mask frame specifies valid and invalid pixels.<br>
133  * This function allows an interpolation positions outside the frame due to the resulting mask.<br>
134  * @param frame The image in which the interpolated patch is located, must be valid
135  * @param mask The mask frame specifying valid and invalid frame pixels, must be valid
136  * @param width The width of the frame (and mask) in pixel, with range [1, infinity)
137  * @param height The height of the frame (and mask) in pixel, with range [1, infinity)
138  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
139  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
140  * @param position The center position of the patch in the image, with range (-infinity, infinity)x(-infinity, infinity) for PC_TOP_LEFT and PC_CENTER
141  * @param patch The target patch, must be valid
142  * @param patchMask The target patch mask, must be valid
143  * @param patchWidth The width of the image patch in pixel, with range [1, infinity)
144  * @param patchHeight The height of the image patch in pixel, with range [1, infinity)
145  * @param patchPaddingElements The number of padding elements at the end of each patch row, in elements, with range [0, infinity)
146  * @param patchMaskPaddingElements The number of padding elements at the end of each patch mask row, in elements, with range [0, infinity)
147  * @param maskValue The 8 bit mask value for valid pixels, an invalid pixel is defined by 0xFF - maskValue
148  * @tparam tChannels The number of frame channels, with range [1, infinity)
149  * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
150  * @tparam TScalar The scalar data type of the sub-pixel position
151  */
152  template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar = Scalar>
153  static void interpolatePatchWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2<TScalar>& position, uint8_t* patch, uint8_t* patchMask, const unsigned int patchWidth, const unsigned int patchHeight, const unsigned int patchPaddingElements, const unsigned int patchMaskPaddingElements, const uint8_t maskValue = 0xFFu);
154 
155  /**
156  * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
157  * Pixels in the square region pointing outside the frame are mirrored back into the frame.
158  * @param frame The image in which the interpolated patch is located, must be valid
159  * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
160  * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
161  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
162  * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
163  * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
164  * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
165  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
166  */
167  template <unsigned int tChannels>
168  static void interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* const buffer, const Vector2& position, const unsigned int patchSize);
169 
170  /**
171  * Interpolates the content of a square region inside a given frame into a buffer with size of the square window.
172  * Pixels in the square region pointing outside the frame are mirrored back into the frame.
173  * @param frame The image in which the interpolated patch is located, must be valid
174  * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
175  * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
176  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
177  * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
178  * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
179  * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
180  * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
181  */
182  template <unsigned int tChannels, unsigned int tPatchSize>
183  static void interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position);
184 
185  /**
186  * Interpolates the content of a source triangle to target triangle.
187  * @param source The source frame, must be valid
188  * @param target The target frame, must be valid
189  * @param sourceTriangle The source triangle holding the frame content to be interpolated, must be valid
190  * @param targetTriangle The target triangle receiving the frame content to be interpolated, must be valid
191  * @param sourceWidth The width of the source frame in pixel, with range [1, infinity)
192  * @param sourceHeight The height of the source frame in pixel, with range [1, infinity)
193  * @param targetWidth The width of the target frame in pixel, with range [1, infinity)
194  * @param targetHeight The height of the target frame in pixel, with range [1, infinity)
195  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
196  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
197  * @param worker An optional worker object to distribute the computation
198  * @tparam tChannels The number of frame channels of the source and target frame, with range [1, infinity)
199  */
200  template <unsigned int tChannels>
201  static void interpolateTriangle8BitPerChannel(const uint8_t* source, uint8_t* target, const PixelTriangle& sourceTriangle, const PixelTriangle& targetTriangle, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
202 
203  /**
204  * Interpolates the content of a source triangle to target triangle.
205  * @param source The source frame, must be valid
206  * @param target The target frame, must be valid
207  * @param sourceTriangle The source triangle holding the frame content to be interpolated, must be valid
208  * @param targetTriangle The target triangle receiving the frame content to be interpolated, must be valid
209  * @param sourceWidth The width of the source frame in pixel, with range [1, infinity)
210  * @param sourceHeight The height of the source frame in pixel, with range [1, infinity)
211  * @param targetWidth The width of the target frame in pixel, with range [1, infinity)
212  * @param targetHeight The height of the target frame in pixel, with range [1, infinity)
213  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
214  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
215  * @param worker An optional worker object to distribute the computation
216  * @tparam tChannels The number of frame channels of the source and target frame, with range [1, infinity)
217  */
218  template <unsigned int tChannels>
219  static void interpolateTriangle8BitPerChannel(const uint8_t* source, uint8_t* target, const Triangle2& sourceTriangle, const Triangle2& targetTriangle, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
220 
221  /**
222  * Interpolates the content of a triangle to another triangle.
223  * @param source The source frame, must be valid
224  * @param target The target frame, must be valid
225  * @param sourceTriangle The source triangle defined in the source frame, must be valid
226  * @param targetTriangle The target triangle defined int he target frame, must be valid
227  * @param worker An optional worker object to distribute the computation
228  * @return True, if succeeded
229  */
230  static bool interpolateTriangle(const Frame& source, Frame& target, const PixelTriangle& sourceTriangle, const PixelTriangle& targetTriangle, Worker* worker = nullptr);
231 
232  /**
233  * Interpolates the content of a triangle to another triangle.
234  * @param source The source frame, must be valid
235  * @param target The target frame, must be valid
236  * @param sourceTriangle The source triangle defined in the source frame, must be valid
237  * @param targetTriangle The target triangle defined int he target frame, must be valid
238  * @param worker An optional worker object to distribute the computation
239  * @return True, if succeeded
240  */
241  static bool interpolateTriangle(const Frame& source, Frame& target, const Triangle2& sourceTriangle, const Triangle2& targetTriangle, Worker* worker = nullptr);
242 
243  /**
244  * Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame which has a corresponding mask frame specifying valid and invalid pixels in the frame.
245  * This function allows an interpolation position outside the frame due to the resulting mask value.<br>
246  * This function uses an integer interpolation with a precision of 1/128.
247  * @param frame The frame to determine the pixel values from, must be valid
248  * @param mask The mask frame specifying valid and invalid frame pixels, must be valid
249  * @param width The width of the frame (and mask) in pixel, with range [1, infinity)
250  * @param height The height of the frame (and mask) in pixel, with range [1, infinity)
251  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
252  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
253  * @param position The position for which the interpolated pixel will be determined, with ranges (-infinity, infinity)x(-infinity, infinity), for PC_TOP_LEFT and PC_CENTER
254  * @param result Resulting pixel values, must be valid, must be valid
255  * @param resultMask The resulting mask value, must be valid
256  * @param maskValue The 8 bit mask value for valid pixels, an invalid pixel is defined by 0xFF - maskValue
257  * @tparam tChannels Number of channels of the given frame, with range [1, infinity)
258  * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
259  * @tparam TScalar The scalar data type of the sub-pixel position
260  */
261  template <unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
262  static inline void interpolatePixelWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2<TScalar>& position, uint8_t* result, uint8_t& resultMask, const uint8_t maskValue = 0xFFu);
263 
264  /**
265  * Transforms a subset of a given input frame into an output frame (with arbitrary frame dimension) by application of a homography.
266  * The output frame must have the same pixel format and pixel origin as the input frame, however the dimension of the output frame can be arbitrary.<br>
267  * Further, this function uses a filter mask for output pixels, only valid output mask pixels will be interpolated.<br>
268  * In case the input position lies outside the input frame's domain, the position will be clamped to ensure a valid interpolation result for each pixel with valid filter mask.
269  * @param input The input frame that will be transformed, must be valid
270  * @param outputFilterMask The filter mask for the output image, with same resolution as the output frame, must be valid
271  * @param output The Output frame resulting by application of the given homography, with same pixel format and pixel origin as the input frame, must have a valid dimension
272  * @param inputWidth The width of the input frame, in pixels, with range [1, infinity)
273  * @param inputHeight The height of the input frame, in pixels, with range [1, infinity)
274  * @param outputWidth The width of the output frame (and filter mask), in pixels, with range [1, infinity)
275  * @param outputHeight The height of the output frame (and filter mask), in pixels, with range [1, infinity)
276  * @param inputPaddingElements The number of padding elements at the end of each input row, in elements, with range [0, infinity)
277  * @param outputFilterMaskPaddingElements The number of padding elements at the end of each output filter mask row, in elements, with range [0, infinity)
278  * @param outputPaddingElements The number of padding elements at the end of each output row, in elements, with range [0, infinity)
279  * @param input_H_output Homography used to transform the given input frame by following equation: inputPoint = input_H_output * outputPoint, must be valid
280  * @param outputBoundingBox Optional bounding box to apply the interpolation to a subset of the output frame only, invalid to handle the entire output frame
281  * @param worker Optional worker object to distribute the computational load
282  * @tparam tChannels The number of frame channels, with range [1, infinity)
283  */
284  template <unsigned int tChannels>
285  static void homographyFilterMask8BitPerChannel(const uint8_t* input, const uint8_t* outputFilterMask, uint8_t* output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskPaddingElements, const unsigned int outputPaddingElements, const SquareMatrix3& input_H_output, const PixelBoundingBox& outputBoundingBox = PixelBoundingBox(), Worker* worker = nullptr);
286 
287  private:
288 
289  /**
290  * Interpolates the subset of a content of a triangle.
291  * @param source The source frame, must be valid
292  * @param target The target frame, must be valid
293  * @param sourceWidth The width of the source frame in pixel, with range [1, infinity)
294  * @param sourceHeight The height of the source frame in pixel, with range [1, infinity)
295  * @param targetWidth The width of the target frame in pixel, with range [1, infinity)
296  * @param targetHeight The height of the target frame in pixel, with range [1, infinity)
297  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
298  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
299  * @param targetTriangle The 2D triangle defined in the target frame, must be valid
300  * @param sourceTriangle The 2D triangle defined in the source frame, must be valid
301  * @param targetLine01 The pixel line between triangle point 0 and 1
302  * @param targetLine02 The pixel line between triangle point 0 and 2
303  * @param targetLine12 The pixel line between triangle point 1 and 2
304  * @param firstTargetRow The first target row to be handled, with range [0, targetHeight - 1u]
305  * @param numberTargetRows The number of target rows to be handled, with range [1, targetHeight - firstRow
306  * @tparam tChannels The number of channels the source and target frame have, with range [1, infinity)
307  */
308  template <unsigned int tChannels>
309  static void interpolateTriangle8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const Triangle2* targetTriangle, const Triangle2* sourceTriangle, const PixelLine* targetLine01, const PixelLine* targetLine02, const PixelLine* targetLine12, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
310 
311  /**
312  * Transforms a subset of a given input frame into an output frame (with arbitrary frame dimension) by application of a homography.
313  * @param input The input frame that will be transformed, must be valid
314  * @param outputFilterMask The filter mask for the output image, with same resolution as the output frame, must be valid
315  * @param output The Output frame resulting by application of the given homography, with same pixel format and pixel origin as the input frame, must have a valid dimension
316  * @param inputWidth The width of the input frame, in pixels, with range [1, infinity)
317  * @param inputHeight The height of the input frame, in pixels, with range [1, infinity)
318  * @param inputPaddingElements The number of padding elements at the end of each input row, in elements, with range [0, infinity)
319  * @param outputFilterMaskStrideElements The number of stride elements at the end of each output filter mask row, in elements, with range [1, infinity)
320  * @param outputStrideElements The number of stride elements at the end of each output row, in elements, with range [tChannels, infinity)
321  * @param input_H_output Homography used to transform the given input frame by following equation: inputPoint = input_H_output * outputPoint, must be valid
322  * @param firstOutputColumn The first output column to be handled, with range [0, output.width() - 1]
323  * @param numberOutputColumns The number of output columns to be handled, with range [output.width() - firstOutputColumn]
324  * @param firstOutputRow The first output row to be handled, with range [0, output.height() - 1]
325  * @param numberOutputRows The number of output rows to be handled, with range [output.height() - firstOutputRow]
326  */
327  template <unsigned int tChannels>
328  static void homographyFilterMask8BitPerChannelSubset(const uint8_t* input, const uint8_t* outputFilterMask, uint8_t* output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskStrideElements, const unsigned int outputStrideElements, const SquareMatrix3* input_H_output, const unsigned int firstOutputColumn, const unsigned int numberOutputColumns, const unsigned int firstOutputRow, const unsigned int numberOutputRows);
329 };
330 
331 template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
332 inline void AdvancedFrameInterpolatorBilinear::interpolatePatch8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t* const buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight)
333 {
334  AdvancedFrameInterpolatorBilinearBase::interpolatePatch8BitPerChannel<tChannels, tPixelCenter, TScalar>(frame, width, framePaddingElements, buffer, position, patchWidth, patchHeight);
335 }
336 
337 template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter>
338 inline void AdvancedFrameInterpolatorBilinear::interpolateSquarePatch8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t* const buffer, const Vector2& position)
339 {
340 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
341 
342  if constexpr (tPatchSize >= 5u)
343  {
344  AdvancedFrameInterpolatorBilinearSSE::interpolateSquarePatch8BitPerChannel<tChannels, tPatchSize, tPixelCenter>(frame, width, framePaddingElements, buffer, position);
345  return;
346  }
347 
348 #endif
349 
350 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
351 
352  if constexpr (tPatchSize >= 5u)
353  {
354  AdvancedFrameInterpolatorBilinearNEON::interpolateSquarePatch8BitPerChannel<tChannels, tPatchSize, tPixelCenter>(frame, width, framePaddingElements, buffer, position);
355  return;
356  }
357 
358 #endif
359 
360  AdvancedFrameInterpolatorBilinearBase::interpolateSquarePatch8BitPerChannelTemplate<tChannels, tPatchSize, tPixelCenter>(frame, width, framePaddingElements, buffer, position);
361 }
362 
363 template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
364 void AdvancedFrameInterpolatorBilinear::interpolatePatchWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2<TScalar>& position, uint8_t* patch, uint8_t* patchMask, const unsigned int patchWidth, const unsigned int patchHeight, const unsigned int patchPaddingElements, const unsigned int patchMaskPaddingElements, const uint8_t maskValue)
365 {
366  ocean_assert(frame != nullptr && mask != nullptr);
367  ocean_assert(patch != nullptr && patchMask != nullptr);
368 
369  ocean_assert(patchWidth >= 1u && patchHeight >= 1u);
370 
371  const unsigned int patchMaskStrideElements = patchWidth + patchMaskPaddingElements;
372 
373  const TScalar left = position.x() - TScalar(patchWidth - 1u) * TScalar(0.5);
374  const TScalar top = position.y() - TScalar(patchHeight - 1u) * TScalar(0.5);
375 
376  for (unsigned int y = 0u; y < patchHeight; ++y)
377  {
378  for (unsigned int x = 0u; x < patchWidth; ++x)
379  {
380  interpolatePixelWithMask8BitPerChannel<tChannels, tPixelCenter, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, VectorT2<TScalar>(left + TScalar(x), top + TScalar(y)), patch, patchMask[x], maskValue);
381 
382  patch += tChannels;
383  }
384 
385  patch += patchPaddingElements;
386  patchMask += patchMaskStrideElements;
387  }
388 }
389 
390 template <unsigned int tChannels>
391 void AdvancedFrameInterpolatorBilinear::interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* const buffer, const Vector2& position, const unsigned int patchSize)
392 {
393  AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorder8BitPerChannel<tChannels>(frame, width, height, framePaddingElements, buffer, position, patchSize);
394 }
395 
396 template <unsigned int tChannels, unsigned int tPatchSize>
397 void AdvancedFrameInterpolatorBilinear::interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* const frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* const buffer, const Vector2& position)
398 {
399  AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorderTemplate8BitPerChannel<tChannels, tPatchSize>(frame, width, height, framePaddingElements, buffer, position);
400 }
401 
402 template <typename TScalar>
403 bool AdvancedFrameInterpolatorBilinear::Comfort::interpolatePixelWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelCenter pixelCenter, const VectorT2<TScalar>& position, uint8_t* result, uint8_t& resultMask, const uint8_t maskValue)
404 {
405  ocean_assert(frame != nullptr);
406  ocean_assert(mask != nullptr);
407  ocean_assert(channels >= 1u && channels <= 8u);
408 
409  if (pixelCenter == PC_TOP_LEFT)
410  {
411  switch (channels)
412  {
413  case 1u:
414  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<1u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
415  return true;
416 
417  case 2u:
418  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<2u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
419  return true;
420 
421  case 3u:
422  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<3u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
423  return true;
424 
425  case 4u:
426  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<4u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
427  return true;
428 
429  case 5u:
430  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<5u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
431  return true;
432 
433  case 6u:
434  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<6u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
435  return true;
436 
437  case 7u:
438  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<7u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
439  return true;
440 
441  case 8u:
442  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<8u, PC_TOP_LEFT, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
443  return true;
444  }
445  }
446  else
447  {
448  ocean_assert(pixelCenter == PC_CENTER);
449 
450  switch (channels)
451  {
452  case 1u:
453  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<1u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
454  return true;
455 
456  case 2u:
457  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<2u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
458  return true;
459 
460  case 3u:
461  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<3u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
462  return true;
463 
464  case 4u:
465  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<4u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
466  return true;
467 
468  case 5u:
469  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<5u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
470  return true;
471 
472  case 6u:
473  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<6u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
474  return true;
475 
476  case 7u:
477  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<7u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
478  return true;
479 
480  case 8u:
481  AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel<8u, PC_CENTER, TScalar>(frame, mask, width, height, framePaddingElements, maskPaddingElements, position, result, resultMask, maskValue);
482  return true;
483  }
484  }
485 
486  ocean_assert(false && "Invalid channel number");
487  return false;
488 }
489 
490 template <unsigned int tChannels>
491 void AdvancedFrameInterpolatorBilinear::interpolateTriangle8BitPerChannel(const uint8_t* source, uint8_t* target, const PixelTriangle& sourceTriangle, const PixelTriangle& targetTriangle, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
492 {
493  ocean_assert(source && target);
494  ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
495  ocean_assert(targetWidth > 0u && targetHeight > 0u);
496 
497  ocean_assert(sourceTriangle.isValid() && targetTriangle.isValid());
498 
499  const unsigned int targetMinY = targetTriangle.top();
500  const unsigned int targetMaxY = min(targetTriangle.bottom(), targetHeight - 1u);
501 
502  const PixelLine targetLine01(targetTriangle.point0(), targetTriangle.point1());
503  const PixelLine targetLine02(targetTriangle.point0(), targetTriangle.point2());
504  const PixelLine targetLine12(targetTriangle.point1(), targetTriangle.point2());
505 
506  const Triangle2 tTriangle(Vector2(Scalar(targetTriangle.point0().x()), Scalar(targetTriangle.point0().y())),
507  Vector2(Scalar(targetTriangle.point1().x()), Scalar(targetTriangle.point1().y())),
508  Vector2(Scalar(targetTriangle.point2().x()), Scalar(targetTriangle.point2().y())));
509 
510  const Triangle2 sTriangle(Vector2(Scalar(sourceTriangle.point0().x()), Scalar(sourceTriangle.point0().y())),
511  Vector2(Scalar(sourceTriangle.point1().x()), Scalar(sourceTriangle.point1().y())),
512  Vector2(Scalar(sourceTriangle.point2().x()), Scalar(sourceTriangle.point2().y())));
513 
514  if (worker)
515  {
516  worker->executeFunction(Worker::Function::createStatic(&interpolateTriangle8BitPerChannelSubset<tChannels>, source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, &tTriangle, &sTriangle, &targetLine01, &targetLine02, &targetLine12, 0u, 0u), targetMinY, targetMaxY - targetMinY + 1u, 13u, 14u, 20u);
517  }
518  else
519  {
520  interpolateTriangle8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, &tTriangle, &sTriangle, &targetLine01, &targetLine02, &targetLine12, targetMinY, targetMaxY - targetMinY + 1u);
521  }
522 }
523 
524 template <unsigned int tChannels>
525 void AdvancedFrameInterpolatorBilinear::interpolateTriangle8BitPerChannel(const uint8_t* source, uint8_t* target, const Triangle2& sourceTriangle, const Triangle2& targetTriangle, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
526 {
527  ocean_assert(source && target);
528  ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
529  ocean_assert(targetWidth > 0u && targetHeight > 0u);
530 
531  ocean_assert(sourceTriangle.isValid() && targetTriangle.isValid());
532 
533  const PixelTriangle targetPixelTriangle(targetTriangle, targetWidth, targetHeight);
534 
535  const unsigned int targetMinY = min(targetPixelTriangle.point0().y(), min(targetPixelTriangle.point1().y(), targetPixelTriangle.point2().y()));
536  const unsigned int targetMaxY = max(targetPixelTriangle.point0().y(), max(targetPixelTriangle.point1().y(), targetPixelTriangle.point2().y()));
537 
538  const PixelLine targetLine01(targetPixelTriangle.point0(), targetPixelTriangle.point1());
539  const PixelLine targetLine02(targetPixelTriangle.point0(), targetPixelTriangle.point2());
540  const PixelLine targetLine12(targetPixelTriangle.point1(), targetPixelTriangle.point2());
541 
542  if (worker)
543  {
544  worker->executeFunction(Worker::Function::createStatic(&interpolateTriangle8BitPerChannelSubset<tChannels>, source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, &targetTriangle, &sourceTriangle, &targetLine01, &targetLine02, &targetLine12, 0u, 0u), targetMinY, targetMaxY - targetMinY + 1u, 13u, 14u, 20u);
545  }
546  else
547  {
548  interpolateTriangle8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourcePaddingElements, targetPaddingElements, &targetTriangle, &sourceTriangle, &targetLine01, &targetLine02, &targetLine12, targetMinY, targetMaxY - targetMinY + 1u);
549  }
550 }
551 
552 template <unsigned int tChannels>
553 void AdvancedFrameInterpolatorBilinear::interpolateTriangle8BitPerChannelSubset(const uint8_t* source, uint8_t* target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const Triangle2* targetTriangle, const Triangle2* sourceTriangle, const PixelLine* targetLine01, const PixelLine* targetLine02, const PixelLine* targetLine12, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
554 {
555  static_assert(tChannels != 0u, "Invalid data channels!");
556 
557  ocean_assert(source != nullptr && target != nullptr);
558 
559 #ifdef OCEAN_DEBUG
560  const unsigned int targetMinY = (unsigned int)(Numeric::round32(targetTriangle->top()));
561  const unsigned int targetMaxY = min((unsigned int)(Numeric::round32(targetTriangle->bottom())), targetHeight - 1u);
562 
563  ocean_assert(firstTargetRow >= targetMinY);
564  ocean_assert(firstTargetRow + numberTargetRows <= targetMaxY + 1u);
565 #endif
566 
567  ocean_assert_and_suppress_unused(firstTargetRow + numberTargetRows <= targetHeight, targetHeight);
568 
569  const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
570 
571  unsigned int x01, x02, x12;
572 
573  for (unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
574  {
575  unsigned int xMin = 0xFFFFFFFF;
576  unsigned int xMax = 0;
577 
578  if (targetLine01->horizontalIntersection(y, x01))
579  {
580  xMin = min(xMin, x01);
581  xMax = max(xMax, x01);
582 
583  if (targetLine01->isHorizontal())
584  {
585  xMin = min(xMin, min(targetLine01->p0().x(), targetLine01->p1().x()));
586  xMax = max(xMax, max(targetLine01->p0().x(), targetLine01->p1().x()));
587  }
588  }
589 
590  if (targetLine02->horizontalIntersection(y, x02))
591  {
592  xMin = min(xMin, x02);
593  xMax = max(xMax, x02);
594 
595  if (targetLine02->isHorizontal())
596  {
597  xMin = min(xMin, min(targetLine02->p0().x(), targetLine02->p1().x()));
598  xMax = max(xMax, max(targetLine02->p0().x(), targetLine02->p1().x()));
599  }
600  }
601 
602  if (targetLine12->horizontalIntersection(y, x12))
603  {
604  xMin = min(xMin, x12);
605  xMax = max(xMax, x12);
606 
607  if (targetLine12->isHorizontal())
608  {
609  xMin = min(xMin, min(targetLine12->p0().x(), targetLine12->p1().x()));
610  xMax = max(xMax, max(targetLine12->p0().x(), targetLine12->p1().x()));
611  }
612  }
613 
614  uint8_t* const targetRow = target + y * targetStrideElements;
615 
616  for (unsigned int x = xMin; x <= min(xMax, targetWidth - 1u); ++x)
617  {
618  const Vector3 targetPositionBarycentric(targetTriangle->cartesian2barycentric(Vector2(Scalar(x), Scalar(y))));
619  ocean_assert(Triangle2::isValidBarycentric(targetPositionBarycentric));
620 
621  const Vector2 sourcePosition(sourceTriangle->barycentric2cartesian(targetPositionBarycentric));
622  const Vector2 clippedPosition(minmax(Scalar(0), sourcePosition.x(), Scalar(sourceWidth - 1u)), minmax(Scalar(0), sourcePosition.y(), Scalar(sourceHeight - 1u)));
623 
624  CV::FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<tChannels, CV::PC_TOP_LEFT>(source, sourceWidth, sourceHeight, sourcePaddingElements, clippedPosition, targetRow + tChannels * x);
625  }
626  }
627 }
628 
629 template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
630 inline void AdvancedFrameInterpolatorBilinear::interpolatePixelWithMask8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2<TScalar>& position, uint8_t* result, uint8_t& resultMask, const uint8_t maskValue)
631 {
632  static_assert(tChannels != 0u, "Invalid channel number!");
633  static_assert(tPixelCenter == PC_TOP_LEFT || tPixelCenter == PC_CENTER, "Invalid pixel center!");
634 
635  ocean_assert(frame != nullptr && mask != nullptr);
636  ocean_assert(result != nullptr);
637  ocean_assert(width != 0u && height != 0u);
638 
639  const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
640  const unsigned int maskStrideElements = width + maskPaddingElements;
641 
642  const VectorT2<TScalar> shiftedPosition = tPixelCenter == PC_TOP_LEFT ? position : position - VectorT2<TScalar>(TScalar(0.5), TScalar(0.5));
643 
644  const int left = int(NumericT<TScalar>::floor(shiftedPosition.x()));
645  const int top = int(NumericT<TScalar>::floor(shiftedPosition.y()));
646 
647  // check whether the position lies outside the frame
648  if (left < -1 || top < -1 || left >= int(width) || top >= int(height))
649  {
650  resultMask = 0xFFu - maskValue;
651  return;
652  }
653 
654  const TScalar sFactorRight = shiftedPosition.x() - TScalar(left);
655  ocean_assert(sFactorRight >= 0 && sFactorRight <= 1);
656  const unsigned int factorRight = (unsigned int)(sFactorRight * TScalar(128) + TScalar(0.5));
657  const unsigned int factorLeft = 128u - factorRight;
658 
659  const TScalar sFactorBottom = shiftedPosition.y() - TScalar(top);
660  ocean_assert(sFactorBottom >= 0 && sFactorBottom <= 1);
661  const unsigned int factorBottom = (unsigned int)(sFactorBottom * TScalar(128) + TScalar(0.5));
662  const unsigned int factorTop = 128u - factorBottom;
663 
664  const unsigned int factorTopLeft = factorTop * factorLeft;
665  const unsigned int factorTopRight = factorTop * factorRight;
666  const unsigned int factorBottomLeft = factorBottom * factorLeft;
667  const unsigned int factorBottomRight = factorBottom * factorRight;
668 
669  const uint8_t* topLeft = frame + top * int(frameStrideElements) + int(tChannels) * left;
670  const uint8_t* maskTopLeft = mask + top * int(maskStrideElements) + left;
671 
672  const uint32_t stateTopLeft = (left >= 0 && top >= 0 && left < int(width) && top < int(height) && maskTopLeft[0] == maskValue) ? 1u : 0u;
673  const uint32_t stateTopRight = (left >= -1 && left < int(width - 1u) && top >= 0 && top < int(height) && maskTopLeft[1] == maskValue) ? 1u : 0u;
674  const uint32_t stateBottomLeft = (left >= 0 && top >= -1 && left < int(width) && top < int(height - 1u) && maskTopLeft[maskStrideElements] == maskValue) ? 1u : 0u;
675  const uint32_t stateBottomRight = (left >= -1 && left < int(width - 1u) && top >= -1 && top < int(height - 1u) && maskTopLeft[maskStrideElements + 1u] == maskValue) ? 1u : 0u;
676 
677  const uint32_t state = stateTopLeft | (stateTopRight << 8u) | (stateBottomLeft << 16u) | (stateBottomRight << 24u);
678 
679  typedef typename DataType<uint8_t, tChannels>::Type PixelType;
680 
681  switch (state)
682  {
683  // FF FF
684  // FF FF
685  case 0x01010101u:
686  {
687  for (unsigned int n = 0u; n < tChannels; ++n)
688  {
689  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[tChannels + n] * factorTopRight
690  + topLeft[frameStrideElements + n] * factorBottomLeft + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + 8192u) >> 14u);
691  }
692 
693  resultMask = maskValue;
694  return;
695  }
696 
697  // 00 FF
698  // FF FF
699  case 0x01010100u:
700  {
701  const unsigned int factorSum = factorTopRight + factorBottomLeft + factorBottomRight;
702 
703  if (factorSum == 0u)
704  {
705  resultMask = 0xFFu - maskValue;
706  return;
707  }
708 
709  for (unsigned int n = 0u; n < tChannels; ++n)
710  {
711  result[n] = uint8_t((topLeft[tChannels + n] * factorTopRight
712  + topLeft[frameStrideElements + n] * factorBottomLeft + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
713  }
714 
715  resultMask = maskValue;
716  return;
717  }
718 
719  // FF 00
720  // FF FF
721  case 0x01010001u:
722  {
723  const unsigned int factorSum = factorTopLeft + factorBottomLeft + factorBottomRight;
724 
725  if (factorSum == 0u)
726  {
727  resultMask = 0xFFu - maskValue;
728  return;
729  }
730 
731  for (unsigned int n = 0u; n < tChannels; ++n)
732  {
733  result[n] = uint8_t((topLeft[n] * factorTopLeft
734  + topLeft[frameStrideElements + n] * factorBottomLeft + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
735  }
736 
737  resultMask = maskValue;
738  return;
739  }
740 
741  // FF FF
742  // 00 FF
743  case 0x01000101u:
744  {
745  const unsigned int factorSum = factorTopLeft + factorTopRight + factorBottomRight;
746 
747  if (factorSum == 0u)
748  {
749  resultMask = 0xFFu - maskValue;
750  return;
751  }
752 
753  for (unsigned int n = 0u; n < tChannels; ++n)
754  {
755  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[tChannels + n] * factorTopRight
756  + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
757  }
758 
759  resultMask = maskValue;
760  return;
761  }
762 
763  // FF FF
764  // FF 00
765  case 0x00010101u:
766  {
767  const unsigned int factorSum = factorTopLeft + factorTopRight + factorBottomLeft;
768 
769  if (factorSum == 0u)
770  {
771  resultMask = 0xFFu - maskValue;
772  return;
773  }
774 
775  for (unsigned int n = 0u; n < tChannels; ++n)
776  {
777  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[tChannels + n] * factorTopRight
778  + topLeft[frameStrideElements + n] * factorBottomLeft + factorSum / 2u) / factorSum);
779  }
780 
781  resultMask = maskValue;
782  return;
783  }
784 
785  // 00 00
786  // FF FF
787  case 0x01010000u:
788  {
789  const unsigned int factorSum = factorBottomLeft + factorBottomRight;
790 
791  if (factorSum == 0u)
792  {
793  resultMask = 0xFFu - maskValue;
794  return;
795  }
796 
797  for (unsigned int n = 0u; n < tChannels; ++n)
798  {
799  result[n] = uint8_t((topLeft[frameStrideElements + n] * factorBottomLeft + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
800  }
801 
802  resultMask = maskValue;
803  return;
804  }
805 
806  // FF 00
807  // FF 00
808  case 0x00010001u:
809  {
810  const unsigned int factorSum = factorTopLeft + factorBottomLeft;
811 
812  if (factorSum == 0u)
813  {
814  resultMask = 0xFFu - maskValue;
815  return;
816  }
817 
818  for (unsigned int n = 0u; n < tChannels; ++n)
819  {
820  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[frameStrideElements + n] * factorBottomLeft + factorSum / 2u) / factorSum);
821  }
822 
823  resultMask = maskValue;
824  return;
825  }
826 
827  // FF FF
828  // 00 00
829  case 0x00000101u:
830  {
831  const unsigned int factorSum = factorTopLeft + factorTopRight;
832 
833  if (factorSum == 0u)
834  {
835  resultMask = 0xFF - maskValue;
836  return;
837  }
838 
839  for (unsigned int n = 0u; n < tChannels; ++n)
840  {
841  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[tChannels + n] * factorTopRight + factorSum / 2u) / factorSum);
842  }
843 
844  resultMask = maskValue;
845  return;
846  }
847 
848  // 00 FF
849  // 00 FF
850  case 0x01000100u:
851  {
852  const unsigned int factorSum = factorTopRight + factorBottomRight;
853 
854  if (factorSum == 0u)
855  {
856  resultMask = 0xFFu - maskValue;
857  return;
858  }
859 
860  for (unsigned int n = 0u; n < tChannels; ++n)
861  {
862  result[n] = uint8_t((topLeft[tChannels + n] * factorTopRight
863  + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
864  }
865 
866  resultMask = maskValue;
867  return;
868  }
869 
870  // 00 FF
871  // FF 00
872  case 0x00010100u:
873  {
874  const unsigned int factorSum = factorTopRight + factorBottomLeft;
875 
876  if (factorSum == 0u)
877  {
878  resultMask = 0xFFu - maskValue;
879  return;
880  }
881 
882  for (unsigned int n = 0u; n < tChannels; ++n)
883  {
884  result[n] = uint8_t((topLeft[tChannels + n] * factorTopRight
885  + topLeft[frameStrideElements + n] * factorBottomLeft + factorSum / 2u) / factorSum);
886  }
887 
888  resultMask = maskValue;
889  return;
890  }
891 
892  // FF 00
893  // 00 FF
894  case 0x01000001u:
895  {
896  const unsigned int factorSum = factorTopLeft + factorBottomRight;
897 
898  if (factorSum == 0u)
899  {
900  resultMask = 0xFFu - maskValue;
901  return;
902  }
903 
904  for (unsigned int n = 0u; n < tChannels; ++n)
905  {
906  result[n] = uint8_t((topLeft[n] * factorTopLeft + topLeft[frameStrideElements + tChannels + n] * factorBottomRight + factorSum / 2u) / factorSum);
907  }
908 
909  resultMask = maskValue;
910  return;
911  }
912 
913  // 00 00
914  // 00 FF
915  case 0x01000000u:
916  {
917  if (factorBottomRight == 0u)
918  {
919  resultMask = 0xFFu - maskValue;
920  return;
921  }
922 
923  *((PixelType*)(result)) = *((const PixelType*)(topLeft + frameStrideElements) + 1);
924  resultMask = maskValue;
925 
926  return;
927  }
928 
929  // FF 00
930  // 00 00
931  case 0x00000001u:
932  {
933  if (factorTopLeft== 0u)
934  {
935  resultMask = 0xFFu - maskValue;
936  return;
937  }
938 
939  *((PixelType*)(result)) = *((const PixelType*)(topLeft));
940  resultMask = maskValue;
941 
942  return;
943  }
944 
945  // 00 FF
946  // 00 00
947  case 0x00000100u:
948  {
949  if (factorTopRight == 0u)
950  {
951  resultMask = 0xFFu - maskValue;
952  return;
953  }
954 
955  *((PixelType*)(result)) = *((const PixelType*)(topLeft) + 1);
956  resultMask = maskValue;
957 
958  return;
959  }
960 
961  // 00 00
962  // FF 00
963  case 0x00010000u:
964  {
965  if (factorBottomLeft == 0u)
966  {
967  resultMask = 0xFFu - maskValue;
968  return;
969  }
970 
971  *((PixelType*)(result)) = *((const PixelType*)(topLeft + frameStrideElements));
972  resultMask = maskValue;
973 
974  return;
975  }
976 
977  // 00 00
978  // 00 00
979  case 0x00000000u:
980  {
981  resultMask = 0xFFu - maskValue;
982  return;
983  }
984  }
985 
986  ocean_assert(false && "Invalid state!");
987  resultMask = 0xFFu - maskValue;
988 }
989 
990 template <unsigned int tChannels>
991 void AdvancedFrameInterpolatorBilinear::homographyFilterMask8BitPerChannel(const uint8_t* input, const uint8_t* outputFilterMask, uint8_t* output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskPaddingElements, const unsigned int outputPaddingElements, const SquareMatrix3& input_H_output, const PixelBoundingBox& outputBoundingBox, Worker* worker)
992 {
993  static_assert(tChannels >= 1u, "Invalid channel number!");
994 
995  const unsigned int outputFirstColumn = outputBoundingBox ? outputBoundingBox.left() : 0u;
996  const unsigned int outputNumberColumns = outputBoundingBox ? outputBoundingBox.width() : outputWidth;
997 
998  const unsigned int outputFirstRow = outputBoundingBox ? outputBoundingBox.top() : 0u;
999  const unsigned int outputNumberRows = outputBoundingBox ? outputBoundingBox.height() : outputHeight;
1000 
1001  const unsigned int outputFilterMaskStrideElemnets = outputWidth + outputFilterMaskPaddingElements;
1002  const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
1003 
1004  if (worker)
1005  {
1006  worker->executeFunction(Worker::Function::createStatic(&homographyFilterMask8BitPerChannelSubset<tChannels>, input, outputFilterMask, output, inputWidth, inputHeight, inputPaddingElements, outputFilterMaskStrideElemnets, outputStrideElements, &input_H_output, outputFirstColumn, outputNumberColumns, 0u, 0u), outputFirstRow, outputNumberRows, 11u, 12u, 40u);
1007  }
1008  else
1009  {
1010  homographyFilterMask8BitPerChannelSubset<tChannels>(input, outputFilterMask, output, inputWidth, inputHeight, inputPaddingElements, outputFilterMaskStrideElemnets, outputStrideElements, &input_H_output, outputFirstColumn, outputNumberColumns, outputFirstRow, outputNumberRows);
1011  }
1012 }
1013 
1014 template <unsigned int tChannels>
1015 void AdvancedFrameInterpolatorBilinear::homographyFilterMask8BitPerChannelSubset(const uint8_t* input, const uint8_t* outputFilterMask, uint8_t* output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskStrideElements, const unsigned int outputStrideElements, const SquareMatrix3* input_H_output, const unsigned int firstOutputColumn, const unsigned int numberOutputColumns, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
1016 {
1017  static_assert(tChannels >= 1u, "Invalid channel number!");
1018 
1019  ocean_assert(input != nullptr && outputFilterMask != nullptr && output != nullptr);
1020  ocean_assert(inputWidth >= 1u && inputHeight >= 1u);
1021  ocean_assert(outputFilterMaskStrideElements >= 1u && outputStrideElements >= tChannels);
1022 
1023  outputFilterMask += firstOutputRow * outputFilterMaskStrideElements;
1024  output += firstOutputRow * outputStrideElements;
1025 
1026  const Scalar inputWidth1 = Scalar(inputWidth - 1u);
1027  const Scalar inputHeight1 = Scalar(inputHeight - 1u);
1028 
1029  for (unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
1030  {
1031  for (unsigned int x = firstOutputColumn; x < firstOutputColumn + numberOutputColumns; ++x)
1032  {
1033  if (outputFilterMask[x] != 0xFFu)
1034  {
1035  const Vector2 sourcePosition(*input_H_output * Vector2(Scalar(x), Scalar(y)));
1036  const Vector2 clampedPosition(minmax(Scalar(0), sourcePosition.x(), inputWidth1), minmax(Scalar(0), sourcePosition.y(), inputHeight1));
1037 
1038  CV::FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<tChannels, CV::PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, clampedPosition, output + x * tChannels);
1039  }
1040  }
1041 
1042  outputFilterMask += outputFilterMaskStrideElements;
1043  output += outputStrideElements;
1044  }
1045 }
1046 
1047 }
1048 
1049 }
1050 
1051 }
1052 
1053 #endif // META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_H
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition: AdvancedFrameInterpolatorBilinear.h:56
static bool interpolatePixelWithMask8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelCenter pixelCenter, const VectorT2< TScalar > &position, uint8_t *result, uint8_t &resultMask, const uint8_t maskValue=0xFFu)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame whi...
Definition: AdvancedFrameInterpolatorBilinear.h:403
static bool homographyFilterMask(const Frame &input, const Frame &outputFilterMask, Frame &output, const SquareMatrix3 &input_H_output, const PixelBoundingBox &outputBoundingBox=PixelBoundingBox(), Worker *worker=nullptr)
Transforms a given input frame into an output frame (with arbitrary frame dimension) by application o...
This class implements an advanced bilinear frame interpolator.
Definition: AdvancedFrameInterpolatorBilinear.h:47
static void interpolateSquarePatch8BitPerChannel(const uint8_t *const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t *const buffer, const Vector2 &position)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition: AdvancedFrameInterpolatorBilinear.h:338
static void homographyFilterMask8BitPerChannel(const uint8_t *input, const uint8_t *outputFilterMask, uint8_t *output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int outputWidth, const unsigned int outputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskPaddingElements, const unsigned int outputPaddingElements, const SquareMatrix3 &input_H_output, const PixelBoundingBox &outputBoundingBox=PixelBoundingBox(), Worker *worker=nullptr)
Transforms a subset of a given input frame into an output frame (with arbitrary frame dimension) by a...
Definition: AdvancedFrameInterpolatorBilinear.h:991
static void interpolatePixelWithMask8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2< TScalar > &position, uint8_t *result, uint8_t &resultMask, const uint8_t maskValue=0xFFu)
Determines the interpolated pixel values for a given pixel position in an 8 bit per channel frame whi...
Definition: AdvancedFrameInterpolatorBilinear.h:630
static void interpolatePatchWithMask8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const VectorT2< TScalar > &position, uint8_t *patch, uint8_t *patchMask, const unsigned int patchWidth, const unsigned int patchHeight, const unsigned int patchPaddingElements, const unsigned int patchMaskPaddingElements, const uint8_t maskValue=0xFFu)
Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores th...
Definition: AdvancedFrameInterpolatorBilinear.h:364
static bool interpolateTriangle(const Frame &source, Frame &target, const Triangle2 &sourceTriangle, const Triangle2 &targetTriangle, Worker *worker=nullptr)
Interpolates the content of a triangle to another triangle.
static void interpolateSquareMirroredBorder8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t *const buffer, const Vector2 &position, const unsigned int patchSize)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition: AdvancedFrameInterpolatorBilinear.h:391
static void interpolateTriangle8BitPerChannelSubset(const uint8_t *source, uint8_t *target, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const Triangle2 *targetTriangle, const Triangle2 *sourceTriangle, const PixelLine *targetLine01, const PixelLine *targetLine02, const PixelLine *targetLine12, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Interpolates the subset of a content of a triangle.
Definition: AdvancedFrameInterpolatorBilinear.h:553
static bool interpolateTriangle(const Frame &source, Frame &target, const PixelTriangle &sourceTriangle, const PixelTriangle &targetTriangle, Worker *worker=nullptr)
Interpolates the content of a triangle to another triangle.
static void interpolateTriangle8BitPerChannel(const uint8_t *source, uint8_t *target, const PixelTriangle &sourceTriangle, const PixelTriangle &targetTriangle, const unsigned int sourceWidth, const unsigned int sourceHeight, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Interpolates the content of a source triangle to target triangle.
Definition: AdvancedFrameInterpolatorBilinear.h:491
static void homographyFilterMask8BitPerChannelSubset(const uint8_t *input, const uint8_t *outputFilterMask, uint8_t *output, const unsigned int inputWidth, const unsigned int inputHeight, const unsigned int inputPaddingElements, const unsigned int outputFilterMaskStrideElements, const unsigned int outputStrideElements, const SquareMatrix3 *input_H_output, const unsigned int firstOutputColumn, const unsigned int numberOutputColumns, const unsigned int firstOutputRow, const unsigned int numberOutputRows)
Transforms a subset of a given input frame into an output frame (with arbitrary frame dimension) by a...
Definition: AdvancedFrameInterpolatorBilinear.h:1015
static void interpolatePatch8BitPerChannel(const uint8_t *const frame, const unsigned int width, const unsigned int framePaddingElements, uint8_t *const buffer, const VectorT2< TScalar > &position, const unsigned int patchWidth, const unsigned int patchHeight)
Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores th...
Definition: AdvancedFrameInterpolatorBilinear.h:332
This class implements a 2D line with pixel precision.
Definition: PixelLine.h:65
bool isHorizontal() const
Returns whether this line is horizontal.
Definition: PixelLine.h:215
const PixelPositionT< T > & p0() const
Returns the first end point of this line.
Definition: PixelLine.h:203
const PixelPositionT< T > & p1() const
Returns the second end point of this line.
Definition: PixelLine.h:209
bool horizontalIntersection(const T y, T &x) const
Calculates the intersection between this line and a horizontal scan line.
Definition: PixelLine.h:236
This class implements a 2D triangle with pixel precision.
Definition: PixelTriangle.h:70
const PixelPositionT< T > & point1() const
Returns the second corner point of this triangle.
Definition: PixelTriangle.h:233
T bottom() const
Returns the most bottom (including) position of this triangle.
Definition: PixelTriangle.h:266
const PixelPositionT< T > & point0() const
Returns the first corner point of this triangle.
Definition: PixelTriangle.h:227
const PixelPositionT< T > & point2() const
Returns the third corner point of this triangle.
Definition: PixelTriangle.h:239
T top() const
Returns the most top (including) position of this triangle.
Definition: PixelTriangle.h:252
bool isValid() const
Returns whether this triangle holds three valid corner points.
Definition: PixelTriangle.h:273
T left() const
Returns the left (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:416
unsigned int width() const
Returns the width (the number of horizontal including pixels) of this bounding box.
Definition: PixelBoundingBox.h:482
T top() const
Returns the top (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:423
unsigned int height() const
Returns the height (the number of vertical including pixels) of this bounding box.
Definition: PixelBoundingBox.h:489
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
Template class allowing to define an array of data types.
Definition: DataType.h:27
This class implements Ocean's image class.
Definition: Frame.h:1792
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition: Numeric.h:2064
This class implements a 2D triangle with Cartesian coordinates.
Definition: Triangle2.h:81
VectorT3< T > cartesian2barycentric(const VectorT2< T > &cartesian) const
Returns the barycentric coordinate of a given 2D Cartesian coordinate defined in relation to this tri...
Definition: Triangle2.h:767
VectorT2< T > barycentric2cartesian(const VectorT3< T > &barycentric) const
Returns the 2D Cartesian coordinate of a given barycentric coordinate defined in relation to this tri...
Definition: Triangle2.h:758
T top() const
Returns the most top position of this triangle.
Definition: Triangle2.h:446
bool isValid() const
Returns whether this triangle can provide valid barycentric coordinates (for 64 bit floating point va...
Definition: Triangle2.h:806
T bottom() const
Returns the most bottom position of this triangle.
Definition: Triangle2.h:460
static bool isValidBarycentric(const VectorT3< T > &barycentric, const T &epsilon=NumericT< T >::eps())
Returns whether the a barycentric coordinate is valid.
Definition: Triangle.h:77
This class implements a vector with two elements.
Definition: Vector2.h:96
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
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.
T minmax(const T &lowerBoundary, const T &value, const T &upperBoundary)
This function fits a given parameter into a specified value range.
Definition: base/Utilities.h:903
PixelCenter
Definition of individual centers of pixels.
Definition: CV.h:117
PixelBoundingBoxT< unsigned int > PixelBoundingBox
Definition of the default PixelBoundingBox object with data type allowing only positive coordinate va...
Definition: PixelBoundingBox.h:21
@ PC_TOP_LEFT
The center of a pixel is in the upper-left corner of each pixel's square.
Definition: CV.h:133
@ PC_CENTER
The center of a pixel is located in the center of each pixel's square (with an offset of 0....
Definition: CV.h:150
float Scalar
Definition of a scalar type.
Definition: Math.h:128
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15