Ocean
Loading...
Searching...
No Matches
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"
19#include "ocean/base/Worker.h"
20
24
27
30#include "ocean/math/Vector2.h"
31#include "ocean/math/Vector3.h"
32
33namespace Ocean
34{
35
36namespace CV
37{
38
39namespace Advanced
40{
41
42/**
43 * This class implements an advanced bilinear frame interpolator.
44 * @ingroup cvadvanced
45 */
46class 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
331template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
332inline 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
337template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter>
338inline 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
363template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
364void 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
390template <unsigned int tChannels>
391void 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
396template <unsigned int tChannels, unsigned int tPatchSize>
397void 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
402template <typename TScalar>
403bool 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
490template <unsigned int tChannels>
491void 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
524template <unsigned int tChannels>
525void 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
552template <unsigned int tChannels>
553void 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
629template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
630inline 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
990template <unsigned int tChannels>
991void 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
1014template <unsigned int tChannels>
1015void 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
This class implements Ocean's image class.
Definition Frame.h:1808
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:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
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
@ 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:129
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition Vector2.h:28
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Default definition of a type with tBytes bytes.
Definition DataType.h:32