Ocean
Loading...
Searching...
No Matches
AdvancedFrameInterpolatorBilinearBase.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_BASE_H
9#define META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_BASE_H
10
12#include "ocean/cv/SSE.h"
13
16
17#include "ocean/math/Vector2.h"
18
19namespace Ocean
20{
21
22namespace CV
23{
24
25namespace Advanced
26{
27
28/**
29 * This class implements several advanced bilinear frame interpolator functions based e.g., on template parameters.
30 * @ingroup cvadvanced
31 */
33{
34 public:
35
36 /**
37 * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
38 * The center of a pixel is expected to be located at the top-left corner of a pixel.
39 * @param image The image in which the interpolated patch is located, must be valid
40 * @param width The width of the image, in pixel, with range [tPatchSize + 1, infinity)
41 * @param imagePaddingElements The number of padding elements at the end of each image row, in elements, with range [0, infinity)
42 * @param buffer The target buffer with `tChannels * tSize * tSize` elements, must be valid
43 * @param position The center position of the square patch in the image, with range [tPatchSize/2, width - tPatchSize/2 - 1)x[tPatchSize/2, height - tPatchSize/2 - 1) for PC_TOP_LEFT, [0.5 + tPatchSize/2, width - tPatchSize/2 - 0.5)x[0.5 + tPatchSize/2, height - tPatchSize/2 - 0.5) for PC_CENTER
44 * @tparam tChannels The number of frame channels, with range [1, infinity)
45 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
46 * @tparam TScalar The scalar data type of the sub-pixel position
47 */
48 template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
49 static inline void interpolateSquarePatch8BitPerChannelTemplate(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position);
50
51 /**
52 * Interpolates the content of an image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
53 * The center of a pixel is expected to be located at the top-left corner of a pixel.
54 * @param image The image in which the interpolated patch is located, must be valid
55 * @param width The width of the image, in pixel, with range [patchWidth + 1, infinity)
56 * @param imagePaddingElements The number of padding elements at the end of each image row, in elements, with range [0, infinity)
57 * @param buffer The target buffer with `tChannels * tSize * tSize` elements, must be valid
58 * @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
59 * @param patchWidth The width of the image patch in pixel, with range [1, infinity), must be odd
60 * @param patchHeight The height of the image patch in pixel, with range [1, infinity), must be odd
61 * @tparam tChannels The number of frame channels, with range [1, infinity)
62 * @tparam tPixelCenter The pixel center to be used during interpolation, either 'PC_TOP_LEFT' or 'PC_CENTER'
63 * @tparam TScalar The scalar data type of the sub-pixel position
64 */
65 template <unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT, typename TScalar = Scalar>
66 static void interpolatePatch8BitPerChannel(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight);
67
68 /**
69 * Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and stores the interpolated data into a buffer.
70 * Pixels in the square region pointing outside the frame are mirrored back into the frame.
71 * @param frame The image in which the interpolated patch is located, must be valid
72 * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
73 * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
74 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
75 * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
76 * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
77 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
78 * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
79 */
80 template <unsigned int tChannels>
81 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, const unsigned int patchSize);
82
83 /**
84 * Interpolates the content of a square region inside a given frame into a buffer with size of the square window.
85 * Pixels in the square region pointing outside the frame are mirrored back into the frame.
86 * @param frame The image in which the interpolated patch is located, must be valid
87 * @param width The width of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
88 * @param height The height of the image, in pixel, with range [tPatchSize/2 + 1, infinity)
89 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
90 * @param buffer The target buffer with `tChannels * patchSize * patchSize` elements, must be valid
91 * @param position Center position of the square region in the source frame, with range [0, width)x[0, height)
92 * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
93 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
94 */
95 template <unsigned int tChannels, unsigned int tPatchSize>
96 static void interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position);
97
98 /**
99 * Interpolates the content of 2x2 pixels to one pixel.
100 * @param sourceTopLeft Top left position of the 2x2 pixels to interpolate, must be valid
101 * @param sourceBottomLeft Bottom left position of the 2x2 pixels to interpolate, must be valid
102 * @param target Position of the target pixel
103 * @param xFactor Horizontal interpolation factor with range [0, 128]
104 * @param yFactor Vertical interpolation factor with range [0, 128]
105 * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
106 */
107 template <unsigned int tChannels>
108 static inline void interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int xFactor, const unsigned int yFactor);
109
110 /**
111 * Interpolates the content of 2x2 pixels to one pixel.
112 * @param sourceTopLeft Top left position of the 2x2 pixels to interpolate, must be valid
113 * @param sourceBottomLeft Bottom left position of the 2x2 pixels to interpolate, must be valid
114 * @param target Position of the target pixel
115 * @param tx_ty_ (128u - xFactor) * (128u - yFactor)
116 * @param txty_ xFactor * (128u - yFactor)
117 * @param tx_ty (128u - xFactor) * yFactor
118 * @param txty xFactor * yFactor
119 * @tparam tChannels The number of data channels of the frame data, with range [1, infinity)
120 */
121 template <unsigned int tChannels>
122 static inline void interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int tx_ty_, const unsigned int txty_, const unsigned int tx_ty, const unsigned int txty);
123};
124
125template <unsigned int tChannels, unsigned int tPatchSize, PixelCenter tPixelCenter, typename TScalar>
126inline void AdvancedFrameInterpolatorBilinearBase::interpolateSquarePatch8BitPerChannelTemplate(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position)
127{
128 static_assert(tChannels >= 1u, "Invalid channel number!");
129 static_assert(tPatchSize % 2u == 1u, "The patch size must be odd!");
130
131 ocean_assert(image != nullptr && buffer != nullptr);
132 ocean_assert(tPatchSize + 1u <= width);
133
134 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
135
136 const unsigned int imageStrideElements = width * tChannels + imagePaddingElements;
137
138 const VectorT2<TScalar> shiftedPosition = tPixelCenter == PC_TOP_LEFT ? position : position - VectorT2<TScalar>(TScalar(0.5), TScalar(0.5));
139
140 ocean_assert(shiftedPosition.x() >= TScalar(tPatchSize_2) && shiftedPosition.y() >= TScalar(tPatchSize_2));
141 ocean_assert(shiftedPosition.x() < TScalar(width - tPatchSize_2 - 1u));
142
143 const unsigned int left = (unsigned int)(shiftedPosition.x()) - tPatchSize_2;
144 const unsigned int top = (unsigned int)(shiftedPosition.y()) - tPatchSize_2;
145
146 ocean_assert(left + tPatchSize < width);
147
148 const TScalar tx = shiftedPosition.x() - TScalar(int(shiftedPosition.x()));
149 ocean_assert(tx >= TScalar(0) && tx <= TScalar(1));
150 const unsigned int factorRight = (unsigned int)(tx * TScalar(128) + TScalar(0.5));
151 const unsigned int factorLeft = 128u - factorRight;
152
153 const TScalar ty = shiftedPosition.y() - TScalar(int(shiftedPosition.y()));
154 ocean_assert(ty >= 0 && ty <= 1);
155 const unsigned int factorBottom = (unsigned int)(ty * TScalar(128) + TScalar(0.5));
156 const unsigned int factorTop = 128u - factorBottom;
157
158 const unsigned int factorTopLeft = factorLeft * factorTop;
159 const unsigned int factorTopRight = factorRight * factorTop;
160 const unsigned int factorBottomLeft = factorLeft * factorBottom;
161 const unsigned int factorBottomRight = factorRight * factorBottom;
162
163 const uint8_t* imageTop = image + top * imageStrideElements + left * tChannels;
164 const uint8_t* imageBottom = imageTop + imageStrideElements;
165
166 const uint8_t* const imageEnd = imageTop + imageStrideElements * tPatchSize;
167
168 const unsigned int imageRowOffset = imageStrideElements - tChannels * tPatchSize;
169
170 while (imageTop != imageEnd)
171 {
172 ocean_assert(imageTop < imageEnd);
173 ocean_assert((imageTop - image) % imageStrideElements == tChannels * left);
174
175 const uint8_t* const imageEndRow = imageTop + tChannels * tPatchSize;
176
177 while (imageTop != imageEndRow)
178 {
179 ocean_assert(imageTop < imageEnd);
180 ocean_assert(imageTop < imageEndRow);
181
182 for (unsigned int n = 0u; n < tChannels; ++n)
183 {
184 *buffer++ = uint8_t((imageTop[n] * factorTopLeft + imageTop[n + tChannels] * factorTopRight + imageBottom[n] * factorBottomLeft + imageBottom[n + tChannels] * factorBottomRight + 8192u) / 16384u);
185 }
186
187 imageTop += tChannels;
188 imageBottom += tChannels;
189 }
190
191 imageTop += imageRowOffset;
192 imageBottom += imageRowOffset;
193 }
194}
195
196template <unsigned int tChannels, PixelCenter tPixelCenter, typename TScalar>
197void AdvancedFrameInterpolatorBilinearBase::interpolatePatch8BitPerChannel(const uint8_t* const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t* buffer, const VectorT2<TScalar>& position, const unsigned int patchWidth, const unsigned int patchHeight)
198{
199 static_assert(tChannels >= 1u, "Invalid channel number!");
200
201 ocean_assert(image != nullptr && buffer != nullptr);
202 ocean_assert(patchWidth + 1u <= width);
203
204 const unsigned int patchWidth_2 = patchWidth / 2u;
205 const unsigned int patchHeight_2 = patchHeight / 2u;
206
207 const unsigned int imageStrideElements = width * tChannels + imagePaddingElements;
208
209 const VectorT2<TScalar> shiftedPosition = tPixelCenter == PC_TOP_LEFT ? position : position - VectorT2<TScalar>(TScalar(0.5), TScalar(0.5));
210
211 ocean_assert(shiftedPosition.x() >= TScalar(patchWidth_2) && shiftedPosition.y() >= TScalar(patchHeight_2));
212 ocean_assert(shiftedPosition.x() < TScalar(width - patchWidth_2 - 1u));
213
214 const unsigned int left = (unsigned int)(shiftedPosition.x()) - patchWidth_2;
215 const unsigned int top = (unsigned int)(shiftedPosition.y()) - patchHeight_2;
216
217 ocean_assert(left + patchWidth < width);
218
219 const TScalar tx = shiftedPosition.x() - TScalar(int(shiftedPosition.x()));
220 ocean_assert(tx >= TScalar(0) && tx <= TScalar(1));
221 const unsigned int factorRight = (unsigned int)(tx * TScalar(128) + TScalar(0.5));
222 const unsigned int factorLeft = 128u - factorRight;
223
224 const TScalar ty = shiftedPosition.y() - TScalar(int(shiftedPosition.y()));
225 ocean_assert(ty >= 0 && ty <= 1);
226 const unsigned int factorBottom = (unsigned int)(ty * TScalar(128) + TScalar(0.5));
227 const unsigned int factorTop = 128u - factorBottom;
228
229 const unsigned int factorTopLeft = factorLeft * factorTop;
230 const unsigned int factorTopRight = factorRight * factorTop;
231 const unsigned int factorBottomLeft = factorLeft * factorBottom;
232 const unsigned int factorBottomRight = factorRight * factorBottom;
233
234 const uint8_t* imageTop = image + top * imageStrideElements + left * tChannels;
235 const uint8_t* imageBottom = imageTop + imageStrideElements;
236
237 const uint8_t* const imageEnd = imageTop + imageStrideElements * patchHeight;
238
239 const unsigned int imageRowOffset = imageStrideElements - tChannels * patchWidth;
240
241 while (imageTop != imageEnd)
242 {
243 ocean_assert(imageTop < imageEnd);
244 ocean_assert((imageTop - image) % imageStrideElements == tChannels * left);
245
246 const uint8_t* const imageEndRow = imageTop + tChannels * patchWidth;
247
248 while (imageTop != imageEndRow)
249 {
250 ocean_assert(imageTop < imageEnd);
251 ocean_assert(imageTop < imageEndRow);
252
253 for (unsigned int n = 0u; n < tChannels; ++n)
254 {
255 *buffer++ = uint8_t((imageTop[n] * factorTopLeft + imageTop[n + tChannels] * factorTopRight + imageBottom[n] * factorBottomLeft + imageBottom[n + tChannels] * factorBottomRight + 8192u) / 16384u);
256 }
257
258 imageTop += tChannels;
259 imageBottom += tChannels;
260 }
261
262 imageTop += imageRowOffset;
263 imageBottom += imageRowOffset;
264 }
265}
266
267template <unsigned int tChannels>
268void AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorder8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position, const unsigned int patchSize)
269{
270 ocean_assert(frame != nullptr && buffer != nullptr);
271 ocean_assert(patchSize >= 1u && patchSize % 2u == 1u);
272
273 const unsigned int patchSize_2 = patchSize / 2u;
274
275 ocean_assert(position.x() >= Scalar(0) && position.y() >= Scalar(0));
276 ocean_assert(position.x() < Scalar(width) && position.y() < Scalar(height));
277
278 const int left = int(position.x()) - int(patchSize_2);
279 const int top = int(position.y()) - int(patchSize_2);
280
281 const Scalar tx = position.x() - Scalar(patchSize_2) - Scalar(left);
282 ocean_assert(tx >= 0 && tx <= 1);
283 const unsigned int txi = (unsigned int)(tx * Scalar(128) + Scalar(0.5));
284 const unsigned int txi_ = 128u - txi;
285
286 const Scalar ty = position.y() - Scalar(patchSize_2) - Scalar(top);
287 ocean_assert(ty >= 0 && ty <= 1);
288 const unsigned int tyi = (unsigned int)(ty * Scalar(128) + Scalar(0.5));
289 const unsigned int tyi_ = 128u - tyi;
290
291 const unsigned int tx_y_ = txi_ * tyi_;
292 const unsigned int txy_ = txi * tyi_;
293 const unsigned int tx_y = txi_ * tyi;
294 const unsigned int txy = txi * tyi;
295
296 const int frameStrideElements = int(width * tChannels + framePaddingElements);
297
298 const uint8_t* frameTop = frame + top * frameStrideElements + left * int(tChannels);
299 const uint8_t* frameBottom = frameTop + frameStrideElements;
300
301 for (unsigned int y = 0u; y < patchSize; ++y)
302 {
303 const uint8_t* pixelTop = frameTop + CVUtilities::mirrorOffset(y + (unsigned int)(top), height) * frameStrideElements;
304 const uint8_t* pixelBottom = frameBottom + CVUtilities::mirrorOffset(y + (unsigned int)(top) + 1u, height) * frameStrideElements;
305
306 for (int xSigned = left; xSigned < left + int(patchSize); ++xSigned)
307 {
308 const unsigned int x = (unsigned int)(xSigned);
309
310 if (x < width && (x + 1u) < width)
311 {
312 // both pixels lies inside the frame
313
314 for (unsigned int n = 0u; n < tChannels; ++n)
315 {
316 buffer[n] = uint8_t((pixelTop[0] * tx_y_ + pixelTop[tChannels] * txy_ + pixelBottom[0] * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
317
318 ++pixelTop;
319 ++pixelBottom;
320 }
321 }
322 else if (x < width)
323 {
324 // x0 lies inside the frame
325
326 ocean_assert(x + 1u >= width);
327
328 const int offset = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
329
330 for (unsigned int n = 0u; n < tChannels; ++n)
331 {
332 buffer[n] = uint8_t((pixelTop[0] * tx_y_ + *(pixelTop + offset) * txy_ + pixelBottom[0] * tx_y + *(pixelBottom + offset) * txy + 8192u) >> 14u);
333
334 ++pixelTop;
335 ++pixelBottom;
336 }
337 }
338 else if (x + 1u < width)
339 {
340 // x1 lies inside the frame
341
342 ocean_assert(x >= width);
343
344 const int offset = CVUtilities::mirrorOffset(x, width) * int(tChannels);
345
346 for (unsigned int n = 0u; n < tChannels; ++n)
347 {
348 buffer[n] = uint8_t((*(pixelTop + 0 + offset) * tx_y_ + pixelTop[tChannels] * txy_ + *(pixelBottom + 0 + offset) * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
349
350 ++pixelTop;
351 ++pixelBottom;
352 }
353 }
354 else
355 {
356 // neither x0 nor x1 lies inside the frame
357
358 ocean_assert(x >= width && x + 1u >= width);
359
360 const int offsetLeft = CVUtilities::mirrorOffset(x, width) * int(tChannels);
361 const int offsetRight = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
362
363 for (unsigned int n = 0u; n < tChannels; ++n)
364 {
365 buffer[n] = uint8_t((*(pixelTop + 0 + offsetLeft) * tx_y_ + *(pixelTop + offsetRight) * txy_ + *(pixelBottom + 0 + offsetLeft) * tx_y + *(pixelBottom + offsetRight) * txy + 8192u) >> 14u);
366
367 ++pixelTop;
368 ++pixelBottom;
369 }
370 }
371
372 buffer += tChannels;
373 }
374
375 frameTop += frameStrideElements;
376 frameBottom += frameStrideElements;
377 }
378}
379
380template <unsigned int tChannels, unsigned int tPatchSize>
381void AdvancedFrameInterpolatorBilinearBase::interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t* buffer, const Vector2& position)
382{
383 static_assert(tChannels >= 1u, "Invalid channel number!");
384 static_assert(tPatchSize >= 1u && tPatchSize % 2u == 1u, "The patch size must be odd!");
385
386 ocean_assert(frame != nullptr && buffer != nullptr);
387
388 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
389
390 ocean_assert(position.x() >= 0 && position.y() >= 0);
391 ocean_assert(position.x() < Scalar(width) && position.y() < Scalar(height));
392
393 const int left = int(position.x()) - int(tPatchSize_2);
394 const int top = int(position.y()) - int(tPatchSize_2);
395
396 const Scalar tx = position.x() - Scalar(tPatchSize_2) - Scalar(left);
397 ocean_assert(tx >= 0 && tx <= 1);
398 const unsigned int txi = (unsigned int)(tx * Scalar(128) + Scalar(0.5));
399 const unsigned int txi_ = 128u - txi;
400
401 const Scalar ty = position.y() - Scalar(tPatchSize_2) - Scalar(top);
402 ocean_assert(ty >= 0 && ty <= 1);
403 const unsigned int tyi = (unsigned int)(ty * Scalar(128) + Scalar(0.5));
404 const unsigned int tyi_ = 128u - tyi;
405
406 const unsigned int tx_y_ = txi_ * tyi_;
407 const unsigned int txy_ = txi * tyi_;
408 const unsigned int tx_y = txi_ * tyi;
409 const unsigned int txy = txi * tyi;
410
411 const int frameStrideElements = int(width * tChannels + framePaddingElements);
412
413 const uint8_t* frameTop = frame + top * frameStrideElements + left * int(tChannels);
414 const uint8_t* frameBottom = frameTop + frameStrideElements;
415
416 for (unsigned int y = 0u; y < tPatchSize; ++y)
417 {
418 const uint8_t* pixelTop = frameTop + CVUtilities::mirrorOffset(y + (unsigned int)(top), height) * frameStrideElements;
419 const uint8_t* pixelBottom = frameBottom + CVUtilities::mirrorOffset(y + (unsigned int)(top) + 1u, height) * frameStrideElements;
420
421 for (int xSigned = left; xSigned < left + int(tPatchSize); ++xSigned)
422 {
423 const unsigned int x = (unsigned int)(xSigned);
424
425 if (x < width && (x + 1u) < width)
426 {
427 // both pixels lies inside the frame
428
429 for (unsigned int n = 0u; n < tChannels; ++n)
430 {
431 buffer[n] = uint8_t((pixelTop[0] * tx_y_ + pixelTop[tChannels] * txy_ + pixelBottom[0] * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
432
433 ++pixelTop;
434 ++pixelBottom;
435 }
436 }
437 else if (x < width)
438 {
439 // x0 lies inside the frame
440
441 ocean_assert(x + 1u >= width);
442
443 const int offset = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
444
445 for (unsigned int n = 0u; n < tChannels; ++n)
446 {
447 buffer[n] = uint8_t((pixelTop[0] * tx_y_ + *(pixelTop + offset) * txy_ + pixelBottom[0] * tx_y + *(pixelBottom + offset) * txy + 8192u) >> 14u);
448
449 ++pixelTop;
450 ++pixelBottom;
451 }
452 }
453 else if (x + 1u < width)
454 {
455 // x1 lies inside the frame
456
457 ocean_assert(x >= width);
458
459 const int offset = CVUtilities::mirrorOffset(x, width) * int(tChannels);
460
461 for (unsigned int n = 0u; n < tChannels; ++n)
462 {
463 buffer[n] = uint8_t((*(pixelTop + 0 + offset) * tx_y_ + pixelTop[tChannels] * txy_ + *(pixelBottom + 0 + offset) * tx_y + pixelBottom[tChannels] * txy + 8192u) >> 14u);
464
465 ++pixelTop;
466 ++pixelBottom;
467 }
468 }
469 else
470 {
471 // neither x0 nor x1 lies inside the frame
472
473 ocean_assert(x >= width && x + 1u >= width);
474
475 const int offsetLeft = CVUtilities::mirrorOffset(x, width) * int(tChannels);
476 const int offsetRight = CVUtilities::mirrorOffset(x + 1u, width) * int(tChannels) + int(tChannels);
477
478 for (unsigned int n = 0u; n < tChannels; ++n)
479 {
480 buffer[n] = uint8_t((*(pixelTop + 0 + offsetLeft) * tx_y_ + *(pixelTop + offsetRight) * txy_ + *(pixelBottom + 0 + offsetLeft) * tx_y + *(pixelBottom + offsetRight) * txy + 8192u) >> 14u);
481
482 ++pixelTop;
483 ++pixelBottom;
484 }
485 }
486
487 buffer += tChannels;
488 }
489
490 frameTop += frameStrideElements;
491 frameBottom += frameStrideElements;
492 }
493}
494
495template <unsigned int tChannels>
496inline void AdvancedFrameInterpolatorBilinearBase::interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int xFactor, const unsigned int yFactor)
497{
498 ocean_assert(sourceTopLeft && target);
499 ocean_assert(xFactor <= 128u && yFactor <= 128u);
500
501 interpolatePixel8BitPerChannel<tChannels>(sourceTopLeft, sourceBottomLeft, target, (128u - xFactor) * (128u - yFactor), xFactor * (128u - yFactor), (128u - xFactor) * yFactor, xFactor * yFactor);
502}
503
504template <unsigned int tChannels>
505inline void AdvancedFrameInterpolatorBilinearBase::interpolatePixel8BitPerChannel(const uint8_t* sourceTopLeft, const uint8_t* sourceBottomLeft, uint8_t* target, const unsigned int tx_ty_, const unsigned int txty_, const unsigned int tx_ty, const unsigned int txty)
506{
507 ocean_assert(sourceTopLeft && target);
508 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
509
510 for (unsigned int n = 0u; n < tChannels; ++n)
511 {
512 target[n] = uint8_t((sourceTopLeft[n] * tx_ty_ + sourceTopLeft[tChannels + n] * txty_ + sourceBottomLeft[n] * tx_ty + sourceBottomLeft[tChannels + n] * txty + 8192u) >> 14u);
513 }
514}
515
516}
517
518}
519
520}
521
522#endif // META_OCEAN_CV_ADVANCED_ADVANCED_FRAME_INTERPOLATOR_BILINEAR_BASE_H
This class implements several advanced bilinear frame interpolator functions based e....
Definition AdvancedFrameInterpolatorBilinearBase.h:33
static void interpolatePatch8BitPerChannel(const uint8_t *const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t *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 AdvancedFrameInterpolatorBilinearBase.h:197
static void interpolatePixel8BitPerChannel(const uint8_t *sourceTopLeft, const uint8_t *sourceBottomLeft, uint8_t *target, const unsigned int xFactor, const unsigned int yFactor)
Interpolates the content of 2x2 pixels to one pixel.
Definition AdvancedFrameInterpolatorBilinearBase.h:496
static void interpolateSquareMirroredBorderTemplate8BitPerChannel(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, uint8_t *buffer, const Vector2 &position)
Interpolates the content of a square region inside a given frame into a buffer with size of the squar...
Definition AdvancedFrameInterpolatorBilinearBase.h:381
static void interpolateSquarePatch8BitPerChannelTemplate(const uint8_t *const image, const unsigned int width, const unsigned int imagePaddingElements, uint8_t *buffer, const VectorT2< TScalar > &position)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition AdvancedFrameInterpolatorBilinearBase.h:126
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, const unsigned int patchSize)
Interpolates the content of a square image patch with sub-pixel accuracy inside a given image and sto...
Definition AdvancedFrameInterpolatorBilinearBase.h:268
static int mirrorOffset(const unsigned int index, const unsigned int elements)
Deprecated.
Definition CVUtilities.h:446
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
@ PC_TOP_LEFT
The center of a pixel is in the upper-left corner of each pixel's square.
Definition CV.h:133
float Scalar
Definition of a scalar type.
Definition Math.h:129
The namespace covering the entire Ocean framework.
Definition Accessor.h:15