Ocean
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"
12 #include "ocean/cv/FramePyramid.h"
15 
16 #include "ocean/base/Worker.h"
17 
18 namespace Ocean
19 {
20 
21 namespace CV
22 {
23 
24 /**
25  * This class implements tri-linear frame interpolator functions.
26  * @ingroup cv
27  */
28 class 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 
214 inline 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 
222 template <unsigned int tChannels>
223 inline 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 
232 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
233 inline 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 
242 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*)>
243 inline 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 
288 template <unsigned int tChannels>
289 inline 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 
302 template <unsigned int tChannels, bool tAlphaAtFront, bool tTransparentIs0xFF>
303 inline 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 
336 template <unsigned int tChannels>
337 inline 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 
349 template <unsigned int tChannels>
350 void 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 
396 template <unsigned int tChannels>
397 inline 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 
409 template <unsigned int tChannels>
410 void 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
Template class allowing to define an array of data types.
Definition: DataType.h:27
This class implements Ocean's image class.
Definition: Frame.h:1760
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:4136
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:4010
unsigned int width() const
Returns the width of the frame format in pixel.
Definition: Frame.h:3111
uint32_t numberPlanes() const
Returns the number of planes of the pixel format of this frame.
Definition: Frame.h:3151
PixelFormat pixelFormat() const
Returns the pixel format of the frame.
Definition: Frame.h:3121
@ 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:3116
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:3374
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:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
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:128
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15