Ocean
Loading...
Searching...
No Matches
FrameInterpolatorTrilinear.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_CV_FRAME_INTERPOLATOR_TRILINEAR_H
9#define META_OCEAN_CV_FRAME_INTERPOLATOR_TRILINEAR_H
10
11#include "ocean/cv/CV.h"
15
16#include "ocean/base/Worker.h"
17
18namespace Ocean
19{
20
21namespace CV
22{
23
24/**
25 * This class implements tri-linear frame interpolator functions.
26 * @ingroup cv
27 */
28class OCEAN_CV_EXPORT FrameInterpolatorTrilinear
29{
30 public:
31
32 /**
33 * Resizes the finest layer of a given frame pyramid by a tri-linear interpolation and optionally uses a worker object to distribute the computational load.
34 * Beware: This method assumes that the pixel format of the target is identical to the pixel format of the frame pyramid.
35 * @param source Frame pyramid provided the frame which will be resized
36 * @param target The target frame buffer
37 * @param targetWidth Width of the target frame in pixel, with range [1, infinity)
38 * @param targetHeight Height of the target frame in pixel, with range [1, infinity)
39 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
40 * @param worker Optional worker object used for load distribution
41 * @return True, if the frame could be resized
42 */
43 static bool resize(const FramePyramid& source, uint8_t* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, Worker* worker = nullptr);
44
45 /**
46 * Resizes the finest layer of a given frame pyramid by a tri-linear interpolation and optionally uses a worker object to distribute the computational load.
47 * @param source Frame pyramid whose finest layer is resized
48 * @param target The target frame buffer
49 * @param worker Optional worker object used for load distribution
50 * @return True, if the frame could be resized
51 */
52 static bool resize(const FramePyramid& source, Frame& target, Worker* worker = nullptr);
53
54 /**
55 * Resizes a given frame by a tri-linear interpolation and optionally uses a worker object to distribute the computational load.
56 * This method creates a new frame pyramid of the source frame, which creates additional computational load.
57 * @param source The source frame buffer to resize
58 * @param target The target frame buffer
59 * @param worker Optional worker object used for load distribution
60 * @return True, if the frame could be resized
61 */
62 static bool resize(const Frame& source, Frame& target, Worker* worker = nullptr);
63
64 /**
65 * Resizes a given frame by a tri-linear interpolation and optionally uses a worker object to distribute the computational load.
66 * This method creates a new frame pyramid of the source frame, which creates additional computational load.
67 * @param frame The frame to be resized in place
68 * @param newWidth New width of the frame in pixel, with range [1, infinity)
69 * @param newHeight New height of the frame in pixel, with range [1, infinity)
70 * @param worker Optional worker object used for load distribution
71 * @return True, if the frame could be resized
72 */
73 static bool resize(Frame& frame, const unsigned int newWidth, const unsigned int newHeight, Worker* worker = nullptr);
74
75 /**
76 * Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
77 * @param sourcePyramid Frame pyramid of input frame that will be transformed
78 * @param width The width of both input images in pixel
79 * @param height The height of both input images pixel
80 * @param homography Homography used to transform the given input frame
81 * @param borderColor Color of undefined pixel positions, the size of the buffer must match to the number of channels, nullptr to assign 0x00 to each channel
82 * @param target Output frame using the given homography
83 * @param worker Optional worker object to distribute the computational load
84 * @tparam tChannels Number of channels of the frame
85 * @see homographyWithCamera8BitPerChannel().
86 */
87 template <unsigned int tChannels>
88 static inline void homography8BitPerChannel(const FramePyramid& sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3& homography, const uint8_t* borderColor, uint8_t* target, Worker* worker = nullptr);
89
90 /**
91 * Calculates a 3D position usable for tri-linear interpolation. The specified image coordinates define the center and four corner positions of quad.
92 * The center position determines the x- and y-coordinate of the resulting 3D sampling position. The corner positions determine the z-coordinate of the
93 * resulting sampling position and the pyramid layers from which samples are retrieved. The vertices have to be specified in clockwise order.
94 * @param layerCount Number of layers supported by the pyramid
95 * @param centerPosition Quad center coordinates in pixels of the finest pyramid layer, used for the actual texture look-up
96 * @param cornerPosition1 First quad corner coordinates in pixels of the finest pyramid layer, used for interpolation between pyramid layers
97 * @param cornerPosition2 Second quad corner coordinates in pixels of the finest pyramid layer, used for interpolation between pyramid layers
98 * @param cornerPosition3 Third quad corner coordinates in pixels of the finest pyramid layer, used for interpolation between pyramid layers
99 * @param cornerPosition4 Fourth quad corner coordinates in pixels of the finest pyramid layer, used for interpolation between pyramid layers
100 * @return The image coordinates (x, y) and layer (z) within the range [0, framePyramid.finestLayerWidth()]x[0, framePyramid.finestLayerWidth()]x[0, layerCount - 1u]
101 */
102 static inline Vector3 interpolatePosition(const unsigned int layerCount, const Vector2& centerPosition, const Vector2& cornerPosition1, const Vector2& cornerPosition2, const Vector2& cornerPosition3, const Vector2& cornerPosition4);
103
104 /**
105 * Performs a pixel lookup in the frame pyramid using tri-linear interpolation.<br>
106 * The position is given as 3D-vector, where x & y specify the 2d image coordinates in pixel units of the finest frame pyramid layer<br>
107 * and z specifies the pyramid layer index. Values with fractions for x,y & z are used as interpolation weights between neighboring pixels and layers.
108 * @param framePyramid Frame pyramid to determine the pixel values from
109 * @param position Image coordinates (x, y) and layer (z), for which pixel values are interpolated using tri-linear interpolation within the range [0, framePyramid.finestLayerWidth()]x[0, framePyramid.finestLayerWidth()]x[0, layerCount - 1u]
110 * @param result Pointer to resulting interpolated pixel values (1Byte per color channel)
111 * @tparam tChannels Defines the number of channels the frame holds
112 */
113 template <unsigned int tChannels>
114 static inline void interpolateFullBorder8BitPerChannel(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result);
115
116 /**
117 * Performs a pixel lookup in the frame pyramid using tri-linear interpolation with infinite transparent frame border.<br>
118 * The position is given as 3D-vector, where x & y specify the 2d image coordinates in pixel units of the finest frame pyramid layer<br>
119 * and z specifies the pyramid layer index. Values with fractions for x,y & z are used as interpolation weights between neighboring pixels and layers.
120 * @param framePyramid Frame pyramid to determine the pixel values from
121 * @param position Image coordinates (x, y) and layer (z), for which pixel values are interpolated using tri-linear interpolation within the range [0, framePyramid.finestLayerWidth()]x[0, framePyramid.finestLayerWidth()]x[0, layerCount - 1u]
122 * @param result Pointer to resulting interpolated pixel values (1Byte per color channel)
123 * @tparam tChannels Defines the number of channels the frame holds
124 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
125 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
126 */
127 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
128 static inline void interpolateInfiniteBorder8BitPerChannelAlpha(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result);
129
130 /**
131 * Renders the passed source frame pyramid into the target frame using tri-linear interpolation.
132 * @param source The source frame pyramid that is read from. The pyramid needs to have the appropriate layers
133 * @param target The target frame buffer
134 * @param targetWidth Width of the target frame in pixel
135 * @param targetHeight Height of the target frame in pixel
136 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
137 * @param worker Optional worker object used for load distribution
138 * @tparam tChannels Defines the number of channels the frame holds
139 */
140 template <unsigned int tChannels>
141 static inline void resize8BitPerChannel(const FramePyramid& source, uint8_t* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, Worker* worker = nullptr);
142
143 protected:
144
145 /**
146 * Performs a pixel lookup in the frame pyramid using tri-linear interpolation.<br>
147 * The position is given as 3D-vector, where x & y specify the 2d image coordinates in pixel units of the finest frame pyramid layer<br>
148 * and z specifies the pyramid layer index. Values with fractions for x,y & z are used as interpolation weights between neighboring pixels and layers.
149 * @param framePyramid Frame pyramid to determine the pixel values from
150 * @param position Image coordinates (x, y) and layer (z), for which pixel values are interpolated using tri-linear interpolation within the range [0, framePyramid.finestLayerWidth()]x[0, framePyramid.finestLayerWidth()]x[0, layerCount - 1u]
151 * @param result Pointer to resulting interpolated pixel values (1Byte per color channel)
152 * @tparam tChannels Defines the number of channels the frame holds
153 * @tparam tBilinearInterpolationFunction The bilinear interpolation function that will be used to interpolate the pixel values within one frame pyramid layer
154 * @tparam tLinearInterpolationFunction The linear interpolation function that will be used to interpolate the pixel values between two frame pyramid layers
155 * @see FrameInterpolatorBilinear::interpolatePixel8BitPerChannel(), FrameInterpolatorBilinear::interpolateFullAlphaBorder8BitPerChannel().
156 */
157 template <unsigned int tChannels, void tBilinearInterpolationFunction(const uint8_t*, const unsigned int, const unsigned int, const unsigned int, const Vector2&, uint8_t*), void tLinearInterpolationFunction(const uint8_t*, const unsigned int, const uint8_t*, uint8_t*)>
158 static inline void interpolate8BitPerChannel(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result);
159
160 /**
161 * This function determines the linear interpolation result for to given layer pixels.
162 * @param first The first pixel data
163 * @param firstFactor First interpolation factor, with range [0, 128]
164 * @param second The second pixel data
165 * @param result Interpolation result
166 * @tparam tChannels Defines the number of channels the frame holds
167 */
168 template <unsigned int tChannels>
169 static inline void interpolateTwoPixels8BitPerChannel(const uint8_t* first, const unsigned int firstFactor, const uint8_t* second, uint8_t* result);
170
171 /**
172 * This function determines the linear interpolation result for to given layer pixels while the interpolation result respects the alpha values of both pixels.
173 * @param first The first pixel data
174 * @param firstFactor First interpolation factor, with range [0, 128]
175 * @param second The second pixel data
176 * @param result Interpolation result
177 * @tparam tChannels Defines the number of channels the frame holds
178 * @tparam tAlphaAtFront True, if the alpha channel is in the front of the data channels
179 * @tparam tTransparentIs0xFF True, if 0xFF is interpreted as fully transparent
180 */
181 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
182 static inline void interpolateTwoPixels8BitPerChannelAlpha(const uint8_t* first, const unsigned int firstFactor, const uint8_t* second, uint8_t* result);
183
184 /**
185 * Renders the passed source frame pyramid into the target frame using tri-linear interpolation.
186 * @param source The source frame pyramid that is read from. The pyramid needs to have the appropriate layers
187 * @param target The target frame buffer
188 * @param targetWidth Width of the target frame in pixel
189 * @param targetHeight Height of the target frame in pixel
190 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
191 * @param firstTargetRow First (including) row to convert
192 * @param numberTargetRows Number of rows to convert
193 * @tparam tChannels Defines the number of channels the frame holds
194 */
195 template <unsigned int tChannels>
196 static void resize8BitPerChannelSubset(const FramePyramid* source, uint8_t* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows);
197
198 /**
199 * Transforms an 8 bit per channel frame using the given homography.
200 * @param sourcePyramid Frame pyramid of input frame that will be transformed
201 * @param width The width of both input images in pixel
202 * @param height The height of both input images pixel
203 * @param homography Homography used to transform the given input frame
204 * @param borderColor Color of undefined pixel positions, the size of the buffer must match to the number of channels, nullptr to assign 0x00 to each channel
205 * @param target Output frame resulting by application of the given homography
206 * @param firstRow The first row to be handled
207 * @param numberRows Number of rows to be handled
208 * @tparam tChannels Number of frame channels
209 */
210 template <unsigned int tChannels>
211 static void homography8BitPerChannelSubset(const FramePyramid* sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3* homography, const uint8_t* borderColor, uint8_t* target, const unsigned int firstRow, const unsigned int numberRows);
212};
213
214inline Vector3 Ocean::CV::FrameInterpolatorTrilinear::interpolatePosition(const unsigned int layerCount, const Vector2& centerPosition, const Vector2& cornerPosition1, const Vector2& cornerPosition2, const Vector2& cornerPosition3, const Vector2& cornerPosition4)
215{
216 const Scalar distance2 = ((cornerPosition3 - cornerPosition1).length() + (cornerPosition4 - cornerPosition2).length()) * Scalar(0.5);
217
218 // 1.4426950408889634073599246810019 == Scalar(1) / Numeric::log(2);
219 return Vector3(centerPosition, minmax<Scalar>(Scalar(0), Numeric::log(distance2) * Scalar(1.4426950408889634073599246810019), Scalar(layerCount - 1u)));
220}
221
222template <unsigned int tChannels>
223inline void FrameInterpolatorTrilinear::interpolateFullBorder8BitPerChannel(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result)
224{
225 ocean_assert(framePyramid.isValid() && result != nullptr);
226 ocean_assert(framePyramid.frameType().numberPlanes() == 1u);
227 ocean_assert(FrameType::formatIsGeneric(framePyramid.frameType().pixelFormat(), FrameType::DT_UNSIGNED_INTEGER_8, tChannels));
228
229 interpolate8BitPerChannel<tChannels, &FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<tChannels, PC_CENTER, Scalar>, &FrameInterpolatorTrilinear::interpolateTwoPixels8BitPerChannel<tChannels> >(framePyramid, position, result);
230}
231
232template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
233inline void FrameInterpolatorTrilinear::interpolateInfiniteBorder8BitPerChannelAlpha(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result)
234{
235 ocean_assert(framePyramid.isValid() && result != nullptr);
236 ocean_assert(framePyramid.frameType().numberPlanes() == 1u);
237 ocean_assert(FrameType::formatIsGeneric(framePyramid.frameType().pixelFormat(), FrameType::DT_UNSIGNED_INTEGER_8, tChannels));
238
239 interpolate8BitPerChannel<tChannels, &FrameInterpolatorBilinearAlpha<tAlphaAtFront, tTransparentIs0xFF>::template interpolateInfiniteBorder8BitPerChannel<tChannels>, &FrameInterpolatorTrilinear::interpolateTwoPixels8BitPerChannelAlpha<tChannels, tAlphaAtFront, tTransparentIs0xFF> >(framePyramid, position, result);
240}
241
242template <unsigned int tChannels, void tBilinearInterpolationFunction(const uint8_t*, const unsigned int, const unsigned int, const unsigned int, const Vector2&, uint8_t*), void tLinearInterpolationFunction(const uint8_t*, const unsigned int, const uint8_t*, uint8_t*)>
243inline void FrameInterpolatorTrilinear::interpolate8BitPerChannel(const FramePyramid& framePyramid, const Vector3& position, uint8_t* result)
244{
245 static_assert(tChannels != 0u, "Invalid channel number!");
246
247 ocean_assert(result != nullptr);
248 ocean_assert(framePyramid.layers() > 0u);
249
250 ocean_assert(position.z() >= 0);
251 ocean_assert(position.z() <= Scalar(framePyramid.layers() - 1u));
252
253 const unsigned int indexFine = (unsigned int)position.z();
254 const unsigned int indexCoarse = indexFine + (indexFine + 1u < framePyramid.layers() ? 1u : 0u);
255
256 const Frame& frameFine = framePyramid.layer(indexFine);
257 const unsigned int widthFine = frameFine.width();
258 const unsigned int heightFine = frameFine.height();
259
260 const Frame& frameCoarse = framePyramid.layer(indexCoarse);
261 const unsigned int widthCoarse = frameCoarse.width();
262 const unsigned int heightCoarse = frameCoarse.height();
263
264 // Pixel scale factor between layer 0 and coarse/fine layer:
265 //const Scalar scaleFineFactor = Scalar(1) / Scalar(1u << indexFine);
266 //const Scalar scaleCoarseFactor = Scalar(1) / Scalar(1u << indexCoarse);
267
268 const Vector2 positionFine = Vector2(position.x() * (Scalar(widthFine) / Scalar(framePyramid.finestWidth())), position.y() * (Scalar(heightFine) / Scalar(framePyramid.finestHeight())));
269 const Vector2 positionCoarse = Vector2(position.x() * (Scalar(widthCoarse) / Scalar(framePyramid.finestWidth())), position.y() * (Scalar(heightCoarse) / Scalar(framePyramid.finestHeight())));
270
271 // Perform bilinear interpolation on the two layers:
272 uint8_t valueFine[tChannels];
273 uint8_t valueCoarse[tChannels];
274
275 tBilinearInterpolationFunction(frameFine.constdata<uint8_t>(), widthFine, heightFine, frameFine.paddingElements(), positionFine, valueFine);
276 tBilinearInterpolationFunction(frameCoarse.constdata<uint8_t>(), widthCoarse, heightCoarse, frameCoarse.paddingElements(), positionCoarse, valueCoarse);
277
278 // Interpolate both values:
279 const Scalar tz = position.z() - Scalar(indexFine);
280 ocean_assert(tz >= 0 && tz <= 1);
281
282 const unsigned int tzi = (unsigned int)(tz * Scalar(128) + Scalar(0.5));
283 ocean_assert(tzi >= 0u && tzi <= 128u);
284
285 tLinearInterpolationFunction(valueCoarse, tzi, valueFine, result);
286}
287
288template <unsigned int tChannels>
289inline void FrameInterpolatorTrilinear::interpolateTwoPixels8BitPerChannel(const uint8_t* first, const unsigned int firstFactor, const uint8_t* second, uint8_t* result)
290{
291 ocean_assert(first && second && result);
292 ocean_assert(firstFactor <= 128u);
293
294 const unsigned int secondFactor = 128u - firstFactor;
295
296 for (unsigned int n = 0u; n < tChannels; ++n)
297 {
298 result[n] = (unsigned char)((first[n] * firstFactor + second[n] * secondFactor + 64u) >> 7u);
299 }
300}
301
302template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
303inline void FrameInterpolatorTrilinear::interpolateTwoPixels8BitPerChannelAlpha(const uint8_t* first, const unsigned int firstFactor, const uint8_t* second, uint8_t* result)
304{
305 ocean_assert(first && second && result);
306 ocean_assert(firstFactor <= 128u);
307
308 const unsigned char firstAlpha = first[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()];
309 const unsigned char secondAlpha = second[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()];
310
311 const unsigned int secondFactor = 128u - firstFactor;
312 const unsigned int denominator = firstFactor * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(firstAlpha)
313 + secondFactor * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(secondAlpha);
314
315 if (denominator != 0u)
316 {
317 const unsigned int denominator_2 = denominator / 2u;
318
319 for (unsigned int n = FrameBlender::SourceOffset<tAlphaAtFront>::data(); n < tChannels + FrameBlender::SourceOffset<tAlphaAtFront>::data() - 1u; ++n)
320 {
321 result[n] = (unsigned char)((first[n] * firstFactor * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(firstAlpha)
322 + second[n] * secondFactor * FrameBlender::alpha8BitToOpaqueIs0xFF<tTransparentIs0xFF>(secondAlpha) + denominator_2) / denominator);
323 }
324
325 result[FrameBlender::SourceOffset<tAlphaAtFront>::template alpha<tChannels>()] = (unsigned char)((firstAlpha * firstFactor + secondAlpha * secondFactor + 64) >> 7u);
326 }
327 else
328 {
329 for (unsigned int n = 0u; n < tChannels; ++n)
330 {
331 result[n] = uint8_t((first[n] * firstFactor + second[n] * secondFactor + 64u) >> 7u);
332 }
333 }
334}
335
336template <unsigned int tChannels>
337inline void FrameInterpolatorTrilinear::resize8BitPerChannel(const FramePyramid& source, uint8_t* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, Worker* worker)
338{
339 if (worker)
340 {
341 worker->executeFunction(Worker::Function::createStatic(&FrameInterpolatorTrilinear::resize8BitPerChannelSubset<tChannels>, &source, target, targetWidth, targetHeight, targetPaddingElements, 0u, 0u), 0u, targetHeight);
342 }
343 else
344 {
345 resize8BitPerChannelSubset<tChannels>(&source, target, targetWidth, targetHeight, targetPaddingElements, 0u, targetHeight);
346 }
347}
348
349template <unsigned int tChannels>
350void FrameInterpolatorTrilinear::resize8BitPerChannelSubset(const FramePyramid* source, uint8_t* target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
351{
352 static_assert(tChannels != 0u, "Invalid channel number!");
353
354 ocean_assert(source != nullptr && target != nullptr);
355 ocean_assert(source->isValid());
356 ocean_assert(source->layers() != 0u);
357
358 ocean_assert(source->finestLayer().numberPlanes() == 1u);
360
361 const unsigned int sourceWidth = source->finestWidth();
362 const unsigned int sourceHeight = source->finestHeight();
363
364 ocean_assert(sourceWidth > 0);
365 ocean_assert(sourceHeight > 0);
366
367 const Scalar targetToSourceX = Scalar(sourceWidth) / Scalar(targetWidth);
368 const Scalar targetToSourceY = Scalar(sourceHeight) / Scalar(targetHeight);
369
370 const Scalar squareDiagonal = Numeric::sqr(targetToSourceX) + Numeric::sqr(targetToSourceY);
371 const Scalar recipprocalLog2 = Scalar(1) / (2 * Numeric::log(2));
372
373 const Scalar layer = minmax(Scalar(0), Numeric::log(squareDiagonal) * recipprocalLog2 - Scalar(0.5), Scalar(source->layers() - 1u)); // log_2(diagonal) - 0.5
374 ocean_assert(Numeric::ceil(layer) <= Scalar(source->layers()));
375
376 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
377
378 Vector3 position = Vector3(0, 0, layer);
379
380 for (unsigned int ty = firstTargetRow; ty < firstTargetRow + numberTargetRows; ++ty)
381 {
382 uint8_t* targetRow = target + ty * targetStrideElements;
383
384 position.y() = targetToSourceY * (Scalar(ty) + Scalar(0.5));
385
386 for (unsigned int tx = 0; tx < targetWidth; ++tx)
387 {
388 position.x() = targetToSourceX * (Scalar(tx) + Scalar(0.5));
389
390 interpolateFullBorder8BitPerChannel<tChannels>(*source, position, targetRow);
391 targetRow += tChannels;
392 }
393 }
394}
395
396template <unsigned int tChannels>
397inline void FrameInterpolatorTrilinear::homography8BitPerChannel(const FramePyramid& sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3& homography, const uint8_t* borderColor, uint8_t* target, Worker* worker)
398{
399 if (worker)
400 {
401 worker->executeFunction(Worker::Function::createStatic(&FrameInterpolatorTrilinear::homography8BitPerChannelSubset<tChannels>, &sourcePyramid, width, height, &homography, borderColor, target, 0u, 0u), 0, height, 6u, 7u, 20u);
402 }
403 else
404 {
405 homography8BitPerChannelSubset<tChannels>(&sourcePyramid, width, height, &homography, borderColor, target, 0u, height);
406 }
407}
408
409template <unsigned int tChannels>
410void FrameInterpolatorTrilinear::homography8BitPerChannelSubset(const FramePyramid* sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3* homography, const uint8_t* borderColor, uint8_t* target, const unsigned int firstRow, const unsigned int numberRows)
411{
412 static_assert(tChannels >= 1u, "Invalid channel number!");
413
414 ocean_assert(sourcePyramid && target);
415 ocean_assert(width > 0u && height > 0u);
416 ocean_assert(homography);
417
418 ocean_assert(firstRow + numberRows <= height);
419
420 const Scalar scalarWidth_1 = Scalar(width - 1u);
421 const Scalar scalarHeight_1 = Scalar(height - 1u);
422
423 typedef typename DataType<uint8_t, tChannels>::Type PixelType;
424
425 PixelType zeroColor;
426 memset(&zeroColor, 0x00, sizeof(PixelType));
427 const PixelType* const bColor = borderColor ? (PixelType*)borderColor : &zeroColor;
428
429 PixelType* targetData = (PixelType*)target + firstRow * width;
430
431 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
432 {
433 for (unsigned int x = 0; x < width; ++x)
434 {
435 const Vector2 centerPosition = Vector2(Scalar(x + 0.5), Scalar(y + 0.5));
436 const Vector2 cornerPosition1 = centerPosition + Vector2(-0.5, -0.5);
437 const Vector2 cornerPosition2 = centerPosition + Vector2(0.5, -0.5);
438 const Vector2 cornerPosition3 = centerPosition + Vector2(-0.5, 0.5);
439 const Vector2 cornerPosition4 = centerPosition + Vector2(0.5, 0.5);
440
441 const Vector2 centerPositionHomography(*homography * centerPosition);
442 const Vector2 cornerPosition1Homography(*homography * cornerPosition1);
443 const Vector2 cornerPosition2Homography(*homography * cornerPosition2);
444 const Vector2 cornerPosition3Homography(*homography * cornerPosition3);
445 const Vector2 cornerPosition4Homography(*homography * cornerPosition4);
446
447 const Vector3 pyramidPosition = interpolatePosition(sourcePyramid->layers(), centerPositionHomography, cornerPosition1Homography, cornerPosition2Homography, cornerPosition3Homography, cornerPosition4Homography);
448
449 if (centerPositionHomography.x() < Scalar(0) || centerPositionHomography.x() > scalarWidth_1 || centerPositionHomography.y() < Scalar(0) || centerPositionHomography.y() > scalarHeight_1)
450 {
451 *targetData = *bColor;
452 }
453 else
454 {
455 interpolateFullBorder8BitPerChannel<tChannels>(*sourcePyramid, pyramidPosition, (uint8_t*)targetData);
456 }
457
458 targetData++;
459 }
460 }
461}
462
463}
464
465}
466
467#endif //OCEAN_CV_FRAME_INTERPOLATOR_TRILINEAR_H
Helper class allowing to determine the offset that is necessary to access the alpha channel.
Definition FrameBlender.h:60
This class implements tri-linear frame interpolator functions.
Definition FrameInterpolatorTrilinear.h:29
static Vector3 interpolatePosition(const unsigned int layerCount, const Vector2 &centerPosition, const Vector2 &cornerPosition1, const Vector2 &cornerPosition2, const Vector2 &cornerPosition3, const Vector2 &cornerPosition4)
Calculates a 3D position usable for tri-linear interpolation.
Definition FrameInterpolatorTrilinear.h:214
static void interpolateInfiniteBorder8BitPerChannelAlpha(const FramePyramid &framePyramid, const Vector3 &position, uint8_t *result)
Performs a pixel lookup in the frame pyramid using tri-linear interpolation with infinite transparent...
Definition FrameInterpolatorTrilinear.h:233
static void homography8BitPerChannel(const FramePyramid &sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3 &homography, const uint8_t *borderColor, uint8_t *target, Worker *worker=nullptr)
Transforms a given 8 bit per channel input frame into an output frame by application of a homography.
Definition FrameInterpolatorTrilinear.h:397
static bool resize(Frame &frame, const unsigned int newWidth, const unsigned int newHeight, Worker *worker=nullptr)
Resizes a given frame by a tri-linear interpolation and optionally uses a worker object to distribute...
static void interpolate8BitPerChannel(const FramePyramid &framePyramid, const Vector3 &position, uint8_t *result)
Performs a pixel lookup in the frame pyramid using tri-linear interpolation.
Definition FrameInterpolatorTrilinear.h:243
static bool resize(const FramePyramid &source, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Resizes the finest layer of a given frame pyramid by a tri-linear interpolation and optionally uses a...
static void homography8BitPerChannelSubset(const FramePyramid *sourcePyramid, const unsigned int width, const unsigned int height, const SquareMatrix3 *homography, const uint8_t *borderColor, uint8_t *target, const unsigned int firstRow, const unsigned int numberRows)
Transforms an 8 bit per channel frame using the given homography.
Definition FrameInterpolatorTrilinear.h:410
static void interpolateTwoPixels8BitPerChannelAlpha(const uint8_t *first, const unsigned int firstFactor, const uint8_t *second, uint8_t *result)
This function determines the linear interpolation result for to given layer pixels while the interpol...
Definition FrameInterpolatorTrilinear.h:303
static void resize8BitPerChannel(const FramePyramid &source, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Renders the passed source frame pyramid into the target frame using tri-linear interpolation.
Definition FrameInterpolatorTrilinear.h:337
static bool resize(const FramePyramid &source, Frame &target, Worker *worker=nullptr)
Resizes the finest layer of a given frame pyramid by a tri-linear interpolation and optionally uses a...
static void resize8BitPerChannelSubset(const FramePyramid *source, uint8_t *target, const unsigned int targetWidth, const unsigned int targetHeight, const unsigned int targetPaddingElements, const unsigned int firstTargetRow, const unsigned int numberTargetRows)
Renders the passed source frame pyramid into the target frame using tri-linear interpolation.
Definition FrameInterpolatorTrilinear.h:350
static void interpolateFullBorder8BitPerChannel(const FramePyramid &framePyramid, const Vector3 &position, uint8_t *result)
Performs a pixel lookup in the frame pyramid using tri-linear interpolation.
Definition FrameInterpolatorTrilinear.h:223
static void interpolateTwoPixels8BitPerChannel(const uint8_t *first, const unsigned int firstFactor, const uint8_t *second, uint8_t *result)
This function determines the linear interpolation result for to given layer pixels.
Definition FrameInterpolatorTrilinear.h:289
static bool resize(const Frame &source, Frame &target, Worker *worker=nullptr)
Resizes a given frame by a tri-linear interpolation and optionally uses a worker object to distribute...
This class implements a frame pyramid.
Definition FramePyramid.h:37
const Frame & finestLayer() const
Returns the finest layer frame of this pyramid.
Definition FramePyramid.h:735
unsigned int finestWidth() const
Returns the width of the finest (first) layer.
Definition FramePyramid.h:778
bool isValid() const
Returns whether this pyramid holds at least one frame layer.
Definition FramePyramid.h:863
unsigned int layers() const
Returns the number of layers this pyramid holds.
Definition FramePyramid.h:761
const FrameType & frameType() const
Returns the frame type of the finest layer.
Definition FramePyramid.h:811
unsigned int finestHeight() const
Returns the height of the finest (first) layer.
Definition FramePyramid.h:784
const Frame & layer(const unsigned int layer) const
Returns the frame of a specified layer.
Definition FramePyramid.h:723
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
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition Frame.h:4248
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition Frame.h:4122
unsigned int width() const
Returns the width of the frame format in pixel.
Definition Frame.h:3170
uint32_t numberPlanes() const
Returns the number of planes of the pixel format of this frame.
Definition Frame.h:3210
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition Frame.h:3180
@ DT_UNSIGNED_INTEGER_8
Unsigned 8 bit integer data type (uint8_t).
Definition Frame.h:41
unsigned int height() const
Returns the height of the frame in pixel.
Definition Frame.h:3175
static bool formatIsGeneric(const PixelFormat pixelFormat, const DataType dataType, const uint32_t channels, const uint32_t planes=1u, const uint32_t widthMultiple=1u, const uint32_t heightMultiple=1u)
Checks whether a given pixel format is a specific layout regarding data channels and data type.
Definition Frame.h:3435
static T log(const T value)
Returns the natural logarithm of a given value (the logarithm to the base e).
Definition Numeric.h:1655
static T ceil(const T value)
Returns the smallest integer value that is not less than the given value.
Definition Numeric.h:1988
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition Numeric.h:1495
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
const T & y() const noexcept
Returns the y value.
Definition Vector3.h:824
const T & x() const noexcept
Returns the x value.
Definition Vector3.h:812
const T & z() const noexcept
Returns the z value.
Definition Vector3.h:836
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
float Scalar
Definition of a scalar type.
Definition Math.h:129
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition Vector3.h:29
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