Ocean
MappingF1.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_SYNTHESIS_MAPPING_F_1_H
9 #define META_OCEAN_CV_SYNTHESIS_MAPPING_F_1_H
10 
13 
14 #include "ocean/base/DataType.h"
15 
18 
21 
23 
24 namespace Ocean
25 {
26 
27 namespace CV
28 {
29 
30 namespace Synthesis
31 {
32 
33 /**
34  * Cost function:
35  *
36  * pixelCost = structureFactor * structureCost + appearanceCost
37  *
38  * structureCost = structureCost' / normalizationStructureCost
39  * appearanceCost = appearanceCost' / normalizationAppearanceCost
40  *
41  * structureCost
42  * pixelCost = structureFactor * structureCost' / normalizationStructureCost + appearanceCost' / normalizationAppearanceCost
43  *
44  * pixelCost' = structureFactor * structureCost * normalizationAppearanceCost + appearanceCost * normalizationStructureCost
45  *
46  * 24bit:
47  * normalizationAppearanceCost = 3 * 255^2 * numberSamples
48  * normalizationStructureCost = width^2 + height^2
49  * @ingroup cvsynthesis
50  */
51 class OCEAN_CV_SYNTHESIS_EXPORT MappingF1 : public MappingF
52 {
53  public:
54 
55  /**
56  * Creates an empty mapping object.
57  */
59 
60  /**
61  * Copies a mapping from a given mapping object.
62  * @param pixelMapping Pixel mapping to be copied
63  */
64  MappingF1(const MappingF1& pixelMapping);
65 
66  /**
67  * Move constructor.
68  * @param mapping The mapping to be moved
69  */
70  MappingF1(MappingF1&& mapping) noexcept;
71 
72  /**
73  * Creates a new mapping object width defined dimension.
74  * Beware: An initial mapping is not provided.<br>
75  * @param width The width of the mapping object in pixel, with range [1, infinity)
76  * @param height The height of the mapping object in pixel, with range [1, infinity)
77  */
78  MappingF1(const unsigned int width, const unsigned int height);
79 
80  /**
81  * Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood and normalizes the result according to the frame dimension.
82  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
83  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width) and must lie inside the target mask
84  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height) and must lie inside the target mask
85  * @param xSource Corresponding horizontal source mapping position for the given position
86  * @param ySource Corresponding vertical source mapping position for the given position
87  * @param targetMask Mask separating target and source pixels for the given target position, width same dimension as this mapping object and with 0xFF for source pixels
88  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
89  * @param maxCost The maximal cost the spatial cost can have, with range [0, infinity)
90  * @return The resulting spatial cost
91  * @tparam tChannels The number of data channels of the frame, with range [1, infinity)
92  */
93  template <unsigned int tChannels>
94  inline Scalar spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const Scalar maxCost) const;
95 
96  /**
97  * Calculates the appearance cost for a given point in a given frame.
98  * @param xTarget Horizontal target position to determine the appearance cost for, with range [2, width - 3] and must lie inside the target mask
99  * @param yTarget Vertical target position to determine the appearance cost for, with range [2, height - 3] and must lie inside the target mask
100  * @param xSource Horizontal source position to determine the appearance cost for, with range [2, width - 3) and must lie outside the target mask
101  * @param ySource Vertical source position to determine the appearance cost for, with range [2, height - 3) and must lie outside the target mask
102  * @param frame The target and source frame to determine the appearance cost on, with same dimension as this mapping object
103  * @param mask The mask separating target and source pixels for the given positions, width same dimension as this mapping object and with 0xFF for source pixels, must be valid
104  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
105  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
106  * @param borderFactor Constant factor to weight the appearance cost of synthesis border pixels (border between target and source pixels) individually, with range [1, infinity)
107  * @tparam tChannels The number of channels of the frame, with range [1, infinity)
108  */
109  template <unsigned int tChannels>
110  unsigned int appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int borderFactor) const;
111 
112  /**
113  * Calculates the appearance cost for a given point between two given frames.
114  * @param xTarget Horizontal target position to determine the appearance cost for, with range [2, width - 3] and must lie inside the target mask
115  * @param yTarget Vertical target position to determine the appearance cost for, with range [2, height - 3] and must lie inside the target mask
116  * @param xSource Horizontal source position to determine the appearance cost for, with range [2, width - 3) and must lie outside the target mask
117  * @param ySource Vertical source position to determine the appearance cost for, with range [2, height - 3) and must lie outside the target mask
118  * @param frame The target and source frame to determine the appearance cost on, with same dimension as this mapping object
119  * @param mask The mask separating target and source pixels for the given positions, width same dimension as this mapping object and with 0xFF for source pixels, must be valid
120  * @param reference The reference frame to determine the appearance cost on (evaluated at the target position), with same frame type as 'frame', must be valid
121  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
122  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
123  * @param referencePaddingElements The number of padding elements at the end of each reference frame row, in elements, with range [0, infinity)
124  * @param borderFactor Constant factor to weight the appearance cost of synthesis border pixels (border between target and source pixels) individually, with range [1, infinity)
125  * @tparam tChannels The number of channels of the frame and reference frame, with range [1, infinity)
126  */
127  template <unsigned int tChannels>
128  inline unsigned int appearanceReferenceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* frame, const uint8_t* mask, const uint8_t* reference, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int referencePaddingElements, const unsigned int borderFactor) const;
129 
130  /**
131  * Applies the current mapping for one given frame.<br>
132  * @see Mapping::applyMapping().
133  */
134  void applyMapping(Frame& frame, const Frame& mask, const unsigned int xStart, const unsigned int xWidth, const unsigned int yStart, const unsigned int yHeight, Worker* worker = nullptr) const override;
135 
136  /**
137  * Applies the current mapping for one given frame.<br>
138  * Only mask pixels will be updated in the frame while the specification of a bounding box in which the mapping will be applied is used to improve the performance of the execution.
139  * @param frame The frame holding source and target area, must be valid
140  * @param mask The 8 bit mask defining source and target area with 0xFF defining a non-mask pixel, with same frame dimension and pixel origin as the provided frame, must be valid
141  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
142  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
143  * @param xStart Horizontal start position of the update area in pixel, with range [0, width())
144  * @param xWidth Width of the update area in pixel, with range [1, width() - xStart]
145  * @param yStart Vertical start position of the update area in pixel, with range [0, height())
146  * @param yHeight Height of the update area in pixel, with range [1, height() - yStart]
147  * @param worker Optional worker object to distribute the computation
148  * @tparam tChannels Number of data channels of the frame, with range [1, infinity)
149  */
150  template <unsigned int tChannels>
151  inline void applyOneFrameMapping8BitPerChannel(uint8_t* const frame, const uint8_t* const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int yStart, const unsigned int yHeight, Worker* worker = nullptr) const;
152 
153  /**
154  * Assigns a pixel mapping with float accuracy.
155  * @param right Mapping to be assigned
156  * @return Reference to this object
157  */
158  inline MappingF1& operator=(const MappingF1& right);
159 
160  /**
161  * Move operator.
162  * @param right Mapping to be moved
163  * @return Reference to this object
164  */
165  inline MappingF1& operator=(MappingF1&& right) noexcept;
166 
167  /**
168  * Assigns a pixel mapping with float accuracy.
169  * @param right Mapping to be assigned
170  * @return Reference to this object
171  */
172  MappingF1& operator=(const MappingI& right);
173 
174  protected:
175 
176  /**
177  * Returns the sum of square differences for a 5x5 block determined between two individual pixel and one sub-pixel position between three individual images.
178  * The result is the sum of two ssd calculations: ssd(image0, image2) * factor02 + ssd(image1, image2) * factor12.<br>
179  * @param image0 The first image to be used, must be valid
180  * @param image1 The second image to be used, must be valid
181  * @param image2 The third image to be used, must be valid
182  * @param width0 The width of the first frame, in pixels, with range [tPatchSize, infinity)
183  * @param width1 The width of the second frame, in pixels) with range [tPatchSize, infinity)
184  * @param width2 The width of the third frame, in pixels, with range [tPatchSize + 1, infinity)
185  * @param image0PaddingElements The number of padding elements at the end of each first image row, in elements, with range [0, infinity)
186  * @param image1PaddingElements The number of padding elements at the end of each second image row, in elements, with range [0, infinity)
187  * @param image2PaddingElements The number of padding elements at the end of each third image row, in elements, with range [0, infinity)
188  * @param factor02 The multiplication factor for the ssd(image0, image2) result
189  * @param factor12 The multiplication factor for the ssd(image1, image2) result
190  * @param centerX0 Horizontal center position of the 5x5 block in the first frame, with range [tPatchSize/2, width0 - tPatchSize/2)
191  * @param centerY0 Vertical center position of the 5x5 block in the first frame, with range [tPatchSize/2, height0 - tPatchSize/2)
192  * @param centerX1 Horizontal center position of the 5x5 block in the first frame, with range [tPatchSize/2, width1 - tPatchSize/2)
193  * @param centerY1 Vertical center position of the 5x5 block in the first frame, with range [tPatchSize/2, height1 - tPatchSize/2)
194  * @param centerX2 Horizontal sub-pixel center position of the 5x5 block in the second frame, with range [tPatchSize/2, width2 - tPatchSize/2 - 1)
195  * @param centerY2 Vertical sub-pixel center position of the 5x5 block in the second frame, with range [tPatchSize/2, height2 - tPatchSize/2 -1)
196  * @return The resulting SSD result
197  * @tparam tChannels Number of data channels of the frame, with range [1, infinity)
198  * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
199  */
200  template <unsigned int tChannels, unsigned int tPatchSize>
201  static inline unsigned int sumSquareDifferencesThreePatch8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const uint8_t* image2, const unsigned int width0, const unsigned int width1, const unsigned int width2, unsigned int image0PaddingElements, const unsigned int image1PaddingElements, const unsigned int image2PaddingElements, const unsigned int factor02, const unsigned int factor12, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const Scalar centerX2, const Scalar centerY2);
202 
203  /**
204  * Calculates the sum of square differences between two 5x5 frame regions in two frames with explicit weighted mask pixels.<br>
205  * Compared to the standard ssd calculation this extended version weights the square difference of mask pixels (value not equal to 0xFF) with a given factor.
206  * @param frame0 Pointer to the top left position in the 5x5 region in the first frame
207  * @param frame1 Pointer to the top left position in the 5x5 region in the second frame
208  * @param mask0 Pointer to the top left position in the 5x5 region in the mask frame, with 0xFF defining a non-mask pixel
209  * @param width0 The width of the first frame (and the mask) in pixel, with range [5, infinity)
210  * @param height0 The height of the first frame (and the mask) in pixel, with range [5, infinity)
211  * @param width1 The width of the second frame in pixel, with range [6, infinity)
212  * @param height1 The height of the second frame in pixel, with range [6, infinity)
213  * @param xPosition0 Horizontal pixel center position of the 5x5 block in the first frame, with range [2, width - 3]
214  * @param yPosition0 Vertical pixel center position of the 5x5 block in the first frame, with range [2, height - 3]
215  * @param xPosition1 Horizontal sub-pixel center position of the 5x5 block in the second frame, with range [2, width - 3)
216  * @param yPosition1 Vertical sub-pixel center position of the 5x5 block in the second frame, with range [2, height - 3)
217  * @param frame0PaddingElements The number of padding elements at the end of each first frame row, in elements, with range [0, infinity)
218  * @param frame1PaddingElements The number of padding elements at the end of each second frame row, in elements, with range [0, infinity)
219  * @param mask0PaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
220  * @param borderFactor Multiplication factor for squared differences of border pixels, with range [1, infinity)
221  * @return Resulting sum of squared differences
222  * @tparam tChannels Number of frame channels, with range [1, infinity)
223  */
224  template <unsigned int tChannels>
225  static inline unsigned int ssd5x5Mask(const uint8_t* frame0, const uint8_t* frame1, const uint8_t* mask0, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int xPosition0, const unsigned int yPosition0, const Scalar xPosition1, const Scalar yPosition1, const unsigned int frame0PaddingElements, const unsigned int frame1PaddingElements, const unsigned int mask0PaddingElements, const unsigned int borderFactor);
226 
227  /**
228  * Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood.
229  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
230  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width) and must lie inside the target mask
231  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height) and must lie inside the target mask
232  * @param xSource Corresponding horizontal source mapping position for the given position
233  * @param ySource Corresponding vertical source mapping position for the given position
234  * @param targetMask Mask separating target and source pixels for the given target position, width same dimension as this mapping object and with 0xFF for source pixels
235  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
236  * @param maxCost The maximal cost the spatial cost can have, with range [0, infinity)
237  * @return Resulting spatial cost for the given points
238  */
239  inline Scalar spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const Scalar maxCost) const;
240 
241  /**
242  * Applies the current mapping in a subset of one given frame.<br>
243  * Only mask pixels will be updated in the frame while the specification of a bounding box in which the mapping will be applied is used to improve the performance of the execution.
244  * @param frame The frame holding source and target area, with frame dimension identical to width() x height()
245  * @param mask The 8 bit mask defining source and target area with 0xFF defining a non-mask pixel, with same frame dimension and pixel origin as the provided frame
246  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
247  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
248  * @param xStart Horizontal start position of the update area in pixel, with range [0, width())
249  * @param xWidth Width of the update area in pixel, with range [1, width() - xStart]
250  * @param firstRow The first row to be handled, with range [0, height())
251  * @param numberRows The number of rows to be handled, with range [1, height() - yStart]
252  * @tparam tChannels Number of data channels of the frame, with range [1, infinity)
253  */
254  template <unsigned int tChannels>
255  void applyOneFrameMapping8BitPerChannelSubset(uint8_t* const frame, const uint8_t* const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int firstRow, const unsigned int numberRows) const;
256 };
257 
258 template <unsigned int tChannels>
259 inline Scalar MappingF1::spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const Scalar maxCost) const
260 {
261  return std::min(spatialCost4Neighborhood(xTarget, yTarget, xSource, ySource, targetMask, targetMaskPaddingElements, maxCost) * Scalar(appearanceCostNormalization<tChannels>()), maxCost);
262 }
263 
264 template <unsigned int tChannels>
265 unsigned int MappingF1::appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int borderFactor) const
266 {
267  static_assert(tChannels >= 1u, "Invalid channel number!");
268 
269  ocean_assert(mask != nullptr && mask != nullptr);
270 
271  ocean_assert(width_ >= 6u && height_ >= 6u);
272 
273  ocean_assert(xTarget >= 2u && xTarget <= width_ - 3u);
274  ocean_assert(yTarget >= 2u && yTarget <= height_ - 3u);
275 
276  ocean_assert(xSource >= Scalar(2) && xSource < Scalar(width_ - 3u));
277  ocean_assert(ySource >= Scalar(2) && ySource < Scalar(height_ - 3u));
278 
279  const unsigned int maskStrideElements = width_ + maskPaddingElements;
280 
281  // the given target coordinate must lie inside the completion mask
282  ocean_assert(mask[yTarget * maskStrideElements + xTarget] != 0xFFu);
283 
284 #ifdef OCEAN_DEBUG
285  const int xSourceRounded(Numeric::round32(xSource));
286  const int ySourceRounded(Numeric::round32(ySource));
287 
288  // the given out-coordinate must lie outside the completion mask
289  ocean_assert(mask[ySourceRounded * maskStrideElements + xSourceRounded] == 0xFFu);
290 #endif
291 
292  constexpr unsigned int patchSize = 5u;
293  constexpr unsigned int patchSize_2 = patchSize / 2u;
294 
295  constexpr unsigned int patchArea = patchSize * patchSize;
296 
297  if (xSource >= Scalar(patchSize_2) && ySource >= Scalar(patchSize_2) && xSource < Scalar(width_ - patchSize_2 - 1u) && ySource < Scalar(height_ - patchSize_2 - 1u))
298  {
299  if (mask[yTarget * maskStrideElements + xTarget] == 0x00u || mask[yTarget * maskStrideElements + xTarget] >= 3u)
300  {
301  ocean_assert(xTarget >= patchSize_2 && yTarget >= patchSize_2 && xTarget <= width_ - patchSize_2 - 1u && yTarget <= height_ - patchSize_2 - 1u);
302 
303  return Advanced::AdvancedSumSquareDifferences::patch8BitPerChannel<tChannels, patchSize>(frame, frame, width_, width_, xTarget, yTarget, xSource, ySource, framePaddingElements, framePaddingElements) * spatialCostNormalization<tChannels>() / patchArea;
304  }
305 
306  if (xTarget >= patchSize_2 && yTarget >= patchSize_2 && xTarget <= width_ - patchSize_2 - 1u && yTarget <= height_ - patchSize_2 - 1u)
307  {
308  return ssd5x5Mask<tChannels>(frame, frame, mask, width_, height_, width_, height_, xTarget, yTarget, xSource, ySource, framePaddingElements, framePaddingElements, maskPaddingElements, borderFactor) * spatialCostNormalization<tChannels>() / patchArea;
309  }
310  }
311 
312  ocean_assert(false && "This should never happen!");
313  return 0xFFFFFF00u; // explicitly below 0xFFFFFFFF = (unsigned int)(-1)
314 }
315 
316 template <unsigned int tChannels>
317 inline unsigned int MappingF1::appearanceReferenceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* frame, const uint8_t* mask, const uint8_t* reference, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int referencePaddingElements, const unsigned int borderFactor) const
318 {
319  static_assert(tChannels >= 1u, "Invalid channel number!");
320 
321  ocean_assert(mask != nullptr && mask != nullptr && reference != nullptr);
322 
323  ocean_assert(width_ >= 6u && height_ >= 6u);
324 
325  ocean_assert(xTarget >= 2u && xTarget <= width_ - 3u);
326  ocean_assert(yTarget >= 2u && yTarget <= height_ - 3u);
327 
328  ocean_assert(xSource >= Scalar(2) && xSource < Scalar(width_ - 3u));
329  ocean_assert(ySource >= Scalar(2) && ySource < Scalar(height_ - 3u));
330 
331  const unsigned int maskStrideElements = width_ + maskPaddingElements;
332 
333  // the given in-coordinate must lie inside the completion mask
334  ocean_assert(mask[yTarget * maskStrideElements + xTarget] != 0xFF);
335 
336 #ifdef OCEAN_DEBUG
337  const int xSourceRounded(Numeric::round32(xSource));
338  const int ySourceRounded(Numeric::round32(ySource));
339 
340  // the given out-coordinate must lie outside the completion mask
341  ocean_assert(mask[ySourceRounded * maskStrideElements + xSourceRounded] == 0xFFu);
342 #endif
343 
344  constexpr unsigned int patchSize = 5u;
345  constexpr unsigned int patchSize_2 = patchSize / 2u;
346 
347  constexpr unsigned int patchArea = patchSize * patchSize;
348 
349  if (xSource >= Scalar(patchSize_2) && ySource >= Scalar(patchSize_2) && xSource < Scalar(width_ - patchSize_2 - 1u) && ySource < Scalar(height_ - patchSize_2 - 1u))
350  {
351  if (mask[yTarget * maskStrideElements + xTarget] == 0x00u || mask[yTarget * maskStrideElements + xTarget] >= 3u)
352  {
353  ocean_assert(xTarget >= patchSize_2 && yTarget >= patchSize_2 && xTarget <= width_ - patchSize_2 - 1u && yTarget <= height_ - patchSize_2 - 1u);
354 
355  return sumSquareDifferencesThreePatch8BitPerChannel<tChannels, patchSize>(frame, reference, frame, width_, width_, width_, framePaddingElements, referencePaddingElements, framePaddingElements, 1u, 5u, xTarget, yTarget, xTarget, yTarget, xSource, ySource) * spatialCostNormalization<tChannels>() / patchArea;
356  }
357 
358  if (xTarget >= patchSize_2 && yTarget >= patchSize_2 && xTarget <= width_ - patchSize_2 - 1u && yTarget <= height_ - patchSize_2 - 1u)
359  {
360  return (5u * ssd5x5Mask<tChannels>(reference, frame, mask, width_, height_, width_, height_, xTarget, yTarget, xSource, ySource, referencePaddingElements, framePaddingElements, maskPaddingElements, borderFactor)
361  + ssd5x5Mask<tChannels>(frame, frame, mask, width_, height_, width_, height_, xTarget, yTarget, xSource, ySource, framePaddingElements, framePaddingElements, maskPaddingElements, borderFactor)) * spatialCostNormalization<tChannels>() / patchArea;
362  }
363  }
364 
365  ocean_assert(false && "This should never happen!");
366  return 0xFFFFFF00u; // explicitly below 0xFFFFFFFF = (unsigned int)(-1)
367 }
368 
369 inline Scalar MappingF1::spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const Scalar maxCost) const
370 {
371  ocean_assert(targetMask != nullptr);
372  ocean_assert(maxCost > Scalar(0));
373 
374  const unsigned int targetMaskStrideElements = width_ + targetMaskPaddingElements;
375 
376  // target position must fit to the layer dimensions
377  ocean_assert(xTarget < width_ && yTarget < height_);
378 
379  // the given in-coordinate must lie inside the completion mask
380  ocean_assert(targetMask[yTarget * targetMaskStrideElements + xTarget] != 0xFF);
381 
382  Scalar cost = maxCost;
383 
384  const uint8_t* targetMaskPointer = targetMask + (int(yTarget) - 1) * int(targetMaskStrideElements) + xTarget;
385  const Vector2* mappingPointer = mappingF_ + (int(yTarget) - 1) * int(width_) + xTarget;
386 
387  // top pixel (north)
388  if (yTarget > 0 && *targetMaskPointer != 0xFF)
389  {
390  ocean_assert(mappingPointer->x() >= 0 && mappingPointer->x() < Scalar(width_));
391  ocean_assert(mappingPointer->y() >= 0 && mappingPointer->y() < Scalar(height_));
392  ocean_assert(*mappingPointer == mappingF_[(yTarget - 1u) * width_ + xTarget]);
393  ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget]);
394 
395  // topPosition - position = -1 (ideal)
396  // => topPosition - position + 1 => min
397  const Scalar localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource + 1);
398 
399  if (localCost == 0)
400  {
401  return 0;
402  }
403 
404  if (localCost < cost)
405  {
406  cost = localCost;
407  }
408  }
409 
410  // forward pointers to next pixel position
411  ocean_assert(width_ >= 1u);
412  targetMaskPointer += targetMaskStrideElements - 1u;
413  mappingPointer += width_ - 1u;
414 
415  // left pixel (west)
416  if (xTarget > 0 && *targetMaskPointer != 0xFF)
417  {
418  ocean_assert(mappingPointer->x() >= 0 && mappingPointer->x() < Scalar(width_));
419  ocean_assert(mappingPointer->y() >= 0 && mappingPointer->y() < Scalar(height_));
420  ocean_assert(*mappingPointer == mappingF_[yTarget * width_ + xTarget - 1u]);
421  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget - 1u]);
422 
423  // leftPosition - position = -1 (ideal)
424  // => leftPosition - position + 1 => min
425  const Scalar localCost = sqr(mappingPointer->x() - xSource + 1) + sqr(mappingPointer->y() - ySource);
426 
427  if (localCost == 0)
428  {
429  return 0;
430  }
431 
432  if (localCost < cost)
433  {
434  cost = localCost;
435  }
436  }
437 
438  // forward pointers to next pixel position
439  targetMaskPointer += 2;
440  mappingPointer += 2;
441 
442  // right pixel (east)
443  if (xTarget + 1 < width_ && *targetMaskPointer != 0xFF)
444  {
445  ocean_assert(mappingPointer->x() >= 0 && mappingPointer->x() < Scalar(width_));
446  ocean_assert(mappingPointer->y() >= 0 && mappingPointer->y() < Scalar(height_));
447  ocean_assert(*mappingPointer == mappingF_[yTarget * width_ + xTarget + 1u]);
448  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget + 1u]);
449 
450  // rightPosition - position = 1 (ideal)
451  // => rightPosition - position - 1 => min
452  const Scalar localCost = sqr(mappingPointer->x() - xSource - 1) + sqr(mappingPointer->y() - ySource);
453 
454  if (localCost == 0)
455  {
456  return 0;
457  }
458 
459  if (localCost < cost)
460  {
461  cost = localCost;
462  }
463  }
464 
465  // forward points one pixel to the right
466  targetMaskPointer += targetMaskStrideElements - 1u;
467  mappingPointer += width_ - 1u;
468 
469  // bottom pixel (south)
470  if (yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
471  {
472  ocean_assert(mappingPointer->x() >= 0 && mappingPointer->x() < Scalar(width_));
473  ocean_assert(mappingPointer->y() >= 0 && mappingPointer->y() < Scalar(height_));
474  ocean_assert(*mappingPointer == mappingF_[(yTarget + 1u) * width_ + xTarget]);
475  ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget]);
476 
477  // bottomPosition - position = 1 (ideal)
478  // => bottomPosition - position - 1 => min
479  const Scalar localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource - 1);
480 
481  if (localCost == 0)
482  {
483  return 0;
484  }
485 
486  if (localCost < cost)
487  {
488  cost = localCost;
489  }
490  }
491 
492  return cost;
493 }
494 
496 {
497  MappingF::operator=(right);
498  return *this;
499 }
500 
501 inline MappingF1& MappingF1::operator=(MappingF1&& right) noexcept
502 {
503  if (this != &right)
504  {
505  MappingF::operator=(std::move(right));
506  }
507 
508  return *this;
509 }
510 
511 template <unsigned int tChannels>
512 inline unsigned int MappingF1::ssd5x5Mask(const uint8_t* frame0, const uint8_t* frame1, const uint8_t* mask0, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int xPosition0, const unsigned int yPosition0, const Scalar xPosition1, const Scalar yPosition1, const unsigned int frame0PaddingElements, const unsigned int frame1PaddingElements, const unsigned int mask0PaddingElements, const unsigned int borderFactor)
513 {
514  static_assert(tChannels >= 1u, "Invalid channel number!");
515 
516  ocean_assert(frame0 != nullptr && frame1 != nullptr && mask0 != nullptr);
517  ocean_assert_and_suppress_unused(width0 >= 5u && height0 >= 5u, height0);
518  ocean_assert_and_suppress_unused(width1 >= 6u && height1 >= 6u, height1);
519 
520  ocean_assert(xPosition0 >= 2u && xPosition0 <= width0 - 2u);
521  ocean_assert(yPosition0 >= 2u && yPosition0 <= height0 - 2u);
522 
523  ocean_assert(xPosition1 >= Scalar(2) && xPosition1 < Scalar(width1 - 3u));
524  ocean_assert(yPosition1 >= Scalar(2) && yPosition1 < Scalar(height1 - 3u));
525 
526  ocean_assert(borderFactor >= 1u);
527 
528  constexpr unsigned int patchSize = 5u;
529  constexpr unsigned int patchArea = patchSize * patchSize;
530 
531  constexpr unsigned int framePatch0PaddingElements = 0u;
532  constexpr unsigned int maskPatch0PaddingElements = 0u;
533 
534  uint8_t framePatch0[patchArea * tChannels];
535  FrameConverter::patchFrame<uint8_t>(frame0, framePatch0, width0, tChannels, xPosition0, yPosition0, patchSize, frame0PaddingElements, framePatch0PaddingElements);
536 
537  uint8_t maskPatch0[patchArea];
538  FrameConverter::patchFrame<uint8_t>(mask0, maskPatch0, width0, 1u, xPosition0, yPosition0, patchSize, mask0PaddingElements, maskPatch0PaddingElements);
539 
540  uint8_t framePatch1[patchArea * tChannels];
541  Advanced::AdvancedFrameInterpolatorBilinear::interpolateSquarePatch8BitPerChannel<tChannels, patchSize, CV::PC_TOP_LEFT>(frame1, width1, frame1PaddingElements, framePatch1, Vector2(xPosition1, yPosition1));
542 
543  unsigned int ssd = 0u;
544 
545  for (unsigned int n = 0u; n < patchArea; ++n)
546  {
547  unsigned int ssdLocal = 0u;
548 
549  for (unsigned int c = 0u; c < tChannels; ++c)
550  {
551  const int value = int(framePatch0[n * tChannels + c]) - int(framePatch1[n * tChannels + c]);
552  ssdLocal += value * value;
553  }
554 
555  if (maskPatch0[n] == 0xFFu)
556  {
557  ssd += ssdLocal * borderFactor;
558  }
559  else
560  {
561  ssd += ssdLocal;
562  }
563  }
564 
565  return ssd;
566 }
567 
568 template <unsigned int tChannels>
569 inline void MappingF1::applyOneFrameMapping8BitPerChannel(uint8_t* const frame, const uint8_t* const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int yStart, const unsigned int yHeight, Worker* worker) const
570 {
571  ocean_assert(frame != nullptr && mask != nullptr);
572 
573  ocean_assert(xStart + xWidth <= width_);
574  ocean_assert(yStart + yHeight <= height_);
575 
576  if (worker)
577  {
578  worker->executeFunction(Worker::Function::create(*this, &MappingF1::applyOneFrameMapping8BitPerChannelSubset<tChannels>, frame, mask, framePaddingElements, maskPaddingElements, xStart, xWidth, 0u, 0u), yStart, yHeight, 6u, 7u, 20u);
579  }
580  else
581  {
582  applyOneFrameMapping8BitPerChannelSubset<tChannels>(frame, mask, framePaddingElements, maskPaddingElements, xStart, xWidth, yStart, yHeight);
583  }
584 }
585 
586 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
587 
588 template <>
589 inline unsigned int MappingF1::sumSquareDifferencesThreePatch8BitPerChannel<3u, 5u>(const uint8_t* image0, const uint8_t* image1, const uint8_t* image2, const unsigned int width0, const unsigned int width1, const unsigned int width2, unsigned int image0PaddingElements, const unsigned int image1PaddingElements, const unsigned int image2PaddingElements, const unsigned int factor02, const unsigned int factor12, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const Scalar centerX2, const Scalar centerY2)
590 {
591  constexpr unsigned int tChannels = 3u;
592  constexpr unsigned int tPatchSize = 5u;
593  constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
594 
595  ocean_assert(image0 != nullptr && image1 != nullptr && image2 != nullptr);
596 
597  ocean_assert(centerX0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2);
598  ocean_assert(centerY0 >= tPatchSize_2);
599 
600  ocean_assert(centerX1 >= tPatchSize_2 && centerX1 < width1 - tPatchSize_2);
601  ocean_assert(centerY1 >= tPatchSize_2);
602 
603  ocean_assert(centerX2 >= Scalar(tPatchSize_2) && centerX2 < Scalar(width2 - tPatchSize_2 - 1u));
604  ocean_assert(centerY2 >= Scalar(tPatchSize_2));
605 
606  const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
607  const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
608  const unsigned int image2StrideElements = width2 * tChannels + image2PaddingElements;
609 
610  const uint8_t* imageTopLeft0 = image0 + (centerY0 - tPatchSize_2) * image0StrideElements + (centerX0 - tPatchSize_2) * tChannels;
611  const uint8_t* imageTopLeft1 = image1 + (centerY1 - tPatchSize_2) * image1StrideElements + (centerX1 - tPatchSize_2) * tChannels;
612  const uint8_t* imageTopLeft2 = image2 + ((unsigned int)(centerY2) - tPatchSize_2) * image2StrideElements + ((unsigned int)(centerX2) - tPatchSize_2) * tChannels;
613 
614  const Scalar scalarFx2 = centerX2 - Scalar((unsigned int)(centerX2));
615  const Scalar scalarFy2 = centerY2 - Scalar((unsigned int)(centerY2));
616 
617  ocean_assert(scalarFx2 >= 0 && scalarFx2 <= 1);
618  ocean_assert(scalarFy2 >= 0 && scalarFy2 <= 1);
619 
620  const unsigned int fx2 = (unsigned int)(Scalar(128) * scalarFx2 + Scalar(0.5));
621  const unsigned int fy2 = (unsigned int)(Scalar(128) * scalarFy2 + Scalar(0.5));
622 
623 
624  SSE::prefetchT0(imageTopLeft0);
625  SSE::prefetchT0(imageTopLeft0 + image0StrideElements);
626 
627  SSE::prefetchT0(imageTopLeft1);
628  SSE::prefetchT0(imageTopLeft1 + image1StrideElements);
629 
630  SSE::prefetchT0(imageTopLeft2);
631  SSE::prefetchT0(imageTopLeft2 + image2StrideElements);
632 
633  const unsigned int fx2_ = 128u - fx2;
634  const unsigned int fy2_ = 128u - fy2;
635 
636  const __m128i f2x_y_ = _mm_set1_epi16(short(fx2_ * fy2_));
637  const __m128i f2xy_ = _mm_set1_epi16(short(fx2 * fy2_));
638  const __m128i f2x_y = _mm_set1_epi16(short(fx2_ * fy2));
639  const __m128i f2xy = _mm_set1_epi16(short(fx2 * fy2));
640 
641  SSE::prefetchT0(imageTopLeft0 + 2u * image0StrideElements);
642  SSE::prefetchT0(imageTopLeft1 + 2u * image1StrideElements);
643  SSE::prefetchT0(imageTopLeft2 + 2u * image2StrideElements);
644 
645  // row 0
646  __m128i image0_row0 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)imageTopLeft0), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
647 
648  __m128i image2_row0Front = _mm_lddqu_si128((__m128i*)imageTopLeft2);
649  __m128i image2_row1Front = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + image2StrideElements));
650  __m128i interpolation2 = SSE::interpolation3Channel24Bit8Elements(image2_row0Front, image2_row1Front, f2x_y_, f2xy_, f2x_y, f2xy);
651 
652  __m128i image1_row0 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)imageTopLeft1), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
653 
654  __m128i image2_row0Back = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 8u));
655  __m128i image2_row1Back = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + image2StrideElements + 8u));
656  interpolation2 = _mm_or_si128(interpolation2, _mm_slli_si128(SSE::interpolation3Channel24Bit8Elements(image2_row0Back, image2_row1Back, f2x_y_, f2xy_, f2x_y, f2xy), 9));
657 
658  __m128i result02 = SSE::sumSquareDifference8Bit16Elements(image0_row0, interpolation2);
659  __m128i result12 = SSE::sumSquareDifference8Bit16Elements(image1_row0, interpolation2);
660 
661 
662  SSE::prefetchT0(imageTopLeft0 + 3u * image0StrideElements);
663  SSE::prefetchT0(imageTopLeft1 + 3u * image1StrideElements);
664  SSE::prefetchT0(imageTopLeft2 + 3u * image2StrideElements);
665 
666 
667  // row 1
668  __m128i image0_row1 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft0 + 1u * image0StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
669 
670  __m128i image2_row2Front = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 2u * image2StrideElements));
671  interpolation2 = SSE::interpolation3Channel24Bit8Elements(image2_row1Front, image2_row2Front, f2x_y_, f2xy_, f2x_y, f2xy);
672 
673  __m128i image1_row1 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft1 + 1u * image1StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
674 
675  __m128i image2_row2Back = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 2u * image2StrideElements + 8u));
676  interpolation2 = _mm_or_si128(interpolation2, _mm_slli_si128(SSE::interpolation3Channel24Bit8Elements(image2_row1Back, image2_row2Back, f2x_y_, f2xy_, f2x_y, f2xy), 9));
677 
678  result02 = _mm_add_epi32(result02, SSE::sumSquareDifference8Bit16Elements(image0_row1, interpolation2));
679  result12 = _mm_add_epi32(result12, SSE::sumSquareDifference8Bit16Elements(image1_row1, interpolation2));
680 
681 
682  SSE::prefetchT0(imageTopLeft0 + 4u * image0StrideElements);
683  SSE::prefetchT0(imageTopLeft1 + 4u * image1StrideElements);
684  SSE::prefetchT0(imageTopLeft2 + 4u * image2StrideElements);
685 
686 
687  // row 2
688  __m128i image0_row2 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft0 + 2u * image0StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
689 
690  __m128i image2_row3Front = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 3u * image2StrideElements));
691  interpolation2 = SSE::interpolation3Channel24Bit8Elements(image2_row2Front, image2_row3Front, f2x_y_, f2xy_, f2x_y, f2xy);
692 
693  __m128i image1_row2 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft1 + 2u * image1StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
694 
695  __m128i image2_row3Back = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 3u * image2StrideElements + 8u));
696  interpolation2 = _mm_or_si128(interpolation2, _mm_slli_si128(SSE::interpolation3Channel24Bit8Elements(image2_row2Back, image2_row3Back, f2x_y_, f2xy_, f2x_y, f2xy), 9));
697 
698  result02 = _mm_add_epi32(result02, SSE::sumSquareDifference8Bit16Elements(image0_row2, interpolation2));
699  result12 = _mm_add_epi32(result12, SSE::sumSquareDifference8Bit16Elements(image1_row2, interpolation2));
700 
701 
702  SSE::prefetchT0(imageTopLeft0 + 5u * image0StrideElements);
703  SSE::prefetchT0(imageTopLeft1 + 5u * image1StrideElements);
704  SSE::prefetchT0(imageTopLeft2 + 5u * image2StrideElements);
705 
706  // row 3
707  __m128i image0_row3 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft0 + 3u * image0StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
708 
709  __m128i image2_row4Front = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 4u * image2StrideElements));
710  interpolation2 = SSE::interpolation3Channel24Bit8Elements(image2_row3Front, image2_row4Front, f2x_y_, f2xy_, f2x_y, f2xy);
711 
712  __m128i image1_row3 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft1 + 3u * image1StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
713 
714  __m128i image2_row4Back = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 4u * image2StrideElements + 8u));
715  interpolation2 = _mm_or_si128(interpolation2, _mm_slli_si128(SSE::interpolation3Channel24Bit8Elements(image2_row3Back, image2_row4Back, f2x_y_, f2xy_, f2x_y, f2xy), 9));
716 
717  result02 = _mm_add_epi32(result02, SSE::sumSquareDifference8Bit16Elements(image0_row3, interpolation2));
718  result12 = _mm_add_epi32(result12, SSE::sumSquareDifference8Bit16Elements(image1_row3, interpolation2));
719 
720 
721 
722  // row 4
723  __m128i image0_row4 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft0 + 4u * image0StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
724 
725  __m128i image2_row5Front = _mm_lddqu_si128((__m128i*)(imageTopLeft2 + 5u * image2StrideElements));
726  interpolation2 = SSE::interpolation3Channel24Bit8Elements(image2_row4Front, image2_row5Front, f2x_y_, f2xy_, f2x_y, f2xy);
727 
728  __m128i image1_row4 = _mm_shuffle_epi8(_mm_lddqu_si128((__m128i*)(imageTopLeft1 + 4u * image1StrideElements)), SSE::set128i(0x0E0D0C0B0A0908A0ull, 0x0706050403020100ull));
729 
730  __m128i image2_row5Back = _mm_srli_si128(_mm_lddqu_si128((__m128i*)(imageTopLeft2 + 5u * image2StrideElements + 8u - 6u)), 6); // here we start 6 bytes earlyer (and shift the bytes later) to avoid a segmentation fault
731  interpolation2 = _mm_or_si128(interpolation2, _mm_slli_si128(SSE::interpolation3Channel24Bit8Elements(image2_row4Back, image2_row5Back, f2x_y_, f2xy_, f2x_y, f2xy), 9));
732 
733  result02 = _mm_add_epi32(result02, SSE::sumSquareDifference8Bit16Elements(image0_row4, interpolation2));
734  result12 = _mm_add_epi32(result12, SSE::sumSquareDifference8Bit16Elements(image1_row4, interpolation2));
735 
736 
737  return (SSE::sum_u32_4(result02)) * factor02 + (SSE::sum_u32_4(result12)) * factor12;
738 }
739 
740 #endif // defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
741 
742 template <unsigned int tChannels, unsigned int tPatchSize>
743 inline unsigned int MappingF1::sumSquareDifferencesThreePatch8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const uint8_t* image2, const unsigned int width0, const unsigned int width1, const unsigned int width2, unsigned int image0PaddingElements, const unsigned int image1PaddingElements, const unsigned int image2PaddingElements, const unsigned int factor02, const unsigned int factor12, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const Scalar centerX2, const Scalar centerY2)
744 {
745  static_assert(tChannels >= 1u, "Invalid channel number!");
746  static_assert(tPatchSize >= 1u && tPatchSize % 2u == 1u, "Invalid channel number!");
747 
748  constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
749 
750  ocean_assert(image0 != nullptr && image1 != nullptr && image2 != nullptr);
751 
752  ocean_assert_and_suppress_unused(centerX0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2, tPatchSize_2);
753  ocean_assert(centerY0 >= tPatchSize_2);
754 
755  ocean_assert(centerX1 >= tPatchSize_2 && centerX1 < width1 - tPatchSize_2);
756  ocean_assert(centerY1 >= tPatchSize_2);
757 
758  ocean_assert(centerX2 >= Scalar(tPatchSize_2) && centerX2 < Scalar(width2 - tPatchSize_2 - 1u));
759  ocean_assert(centerY2 >= Scalar(tPatchSize_2));
760 
761  uint8_t interpolated2[tPatchSize * tPatchSize * tChannels];
762 
763  CV::Advanced::AdvancedFrameInterpolatorBilinear::interpolateSquarePatch8BitPerChannel<tChannels, tPatchSize>(image2, width2, image2PaddingElements, interpolated2, Vector2(centerX2, centerY2));
764 
765  return SumSquareDifferencesBase::patchBuffer8BitPerChannelTemplate<tChannels, tPatchSize>(image0, width0, centerX0, centerY0, image0PaddingElements, interpolated2) * factor02
766  + SumSquareDifferencesBase::patchBuffer8BitPerChannelTemplate<tChannels, tPatchSize>(image1, width1, centerX1, centerY1, image1PaddingElements, interpolated2) * factor12;
767 }
768 
769 template <unsigned int tChannels>
770 void MappingF1::applyOneFrameMapping8BitPerChannelSubset(uint8_t* const frame, const uint8_t* const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int firstRow, const unsigned int numberRows) const
771 {
772  static_assert(tChannels >= 1u, "Invalid channels!");
773 
775 
776  ocean_assert(xStart + xWidth <= width_);
777  ocean_assert(firstRow + numberRows <= height_);
778 
779  const unsigned int frameStrideElements = width_ * tChannels + framePaddingElements;
780  const unsigned int maskStrideElements = width_ + maskPaddingElements;
781 
782  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
783  {
784  DataType* framePixel = ((DataType*)(frame + y * frameStrideElements)) + xStart;
785  const uint8_t* maskPixel = mask + y * maskStrideElements + xStart;
786 
787  const Vector2* mappingPixel = mappingF_ + y * width_ + xStart; // mapping does not contain padding (mappingStride == width_)
788 
789  for (unsigned int n = 0u; n < xWidth; ++n)
790  {
791  if (*maskPixel != 0xFF)
792  {
793  CV::FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<tChannels, CV::PC_TOP_LEFT>(frame, width_, height_, framePaddingElements, *mappingPixel, (uint8_t*)(framePixel));
794  }
795 
796  ++framePixel;
797  ++maskPixel;
798 
799  ++mappingPixel;
800  }
801  }
802 }
803 
804 }
805 
806 }
807 
808 }
809 
810 #endif // META_OCEAN_CV_SYNTHESIS_MAPPING_F_1_H
static void prefetchT0(const void *const data)
Prefetches a block of temporal memory into all cache levels.
Definition: SSE.h:1255
static __m128i sumSquareDifference8Bit16Elements(const uint8_t *const image0, const uint8_t *const image1)
Sum square difference determination for 16 elements with 8 bit precision.
Definition: SSE.h:1533
static OCEAN_FORCE_INLINE unsigned int sum_u32_4(const __m128i &value)
Adds the four (all four) individual 32 bit unsigned integer values of a m128i value and returns the r...
Definition: SSE.h:1322
static __m128i set128i(const unsigned long long high64, const unsigned long long low64)
Sets a 128i value by two 64 bit values.
Definition: SSE.h:3770
static __m128i interpolation3Channel24Bit8Elements(const __m128i &values0, const __m128i &values1, const __m128i &fx_fy_, const __m128i &fxfy_, const __m128i &fx_fy, const __m128i &fxfy)
Interpolates 8 elements of 2x2 blocks for 3 channel 24 bit frames.
Definition: SSE.h:1879
Cost function:
Definition: MappingF1.h:52
void applyOneFrameMapping8BitPerChannel(uint8_t *const frame, const uint8_t *const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int yStart, const unsigned int yHeight, Worker *worker=nullptr) const
Applies the current mapping for one given frame.
Definition: MappingF1.h:569
unsigned int appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int borderFactor) const
Calculates the appearance cost for a given point in a given frame.
Definition: MappingF1.h:265
MappingF1(MappingF1 &&mapping) noexcept
Move constructor.
MappingF1 & operator=(const MappingI &right)
Assigns a pixel mapping with float accuracy.
MappingF1()
Creates an empty mapping object.
MappingF1 & operator=(const MappingF1 &right)
Assigns a pixel mapping with float accuracy.
Definition: MappingF1.h:495
unsigned int appearanceReferenceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t *frame, const uint8_t *mask, const uint8_t *reference, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int referencePaddingElements, const unsigned int borderFactor) const
Calculates the appearance cost for a given point between two given frames.
Definition: MappingF1.h:317
void applyOneFrameMapping8BitPerChannelSubset(uint8_t *const frame, const uint8_t *const mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int firstRow, const unsigned int numberRows) const
Applies the current mapping in a subset of one given frame.
Definition: MappingF1.h:770
Scalar spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const Scalar xSource, const Scalar ySource, const uint8_t *targetMask, const unsigned int targetMaskPaddingElements, const Scalar maxCost) const
Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood and normalizes...
Definition: MappingF1.h:259
static unsigned int sumSquareDifferencesThreePatch8BitPerChannel(const uint8_t *image0, const uint8_t *image1, const uint8_t *image2, const unsigned int width0, const unsigned int width1, const unsigned int width2, unsigned int image0PaddingElements, const unsigned int image1PaddingElements, const unsigned int image2PaddingElements, const unsigned int factor02, const unsigned int factor12, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const Scalar centerX2, const Scalar centerY2)
Returns the sum of square differences for a 5x5 block determined between two individual pixel and one...
Definition: MappingF1.h:743
MappingF1(const MappingF1 &pixelMapping)
Copies a mapping from a given mapping object.
MappingF1(const unsigned int width, const unsigned int height)
Creates a new mapping object width defined dimension.
static unsigned int ssd5x5Mask(const uint8_t *frame0, const uint8_t *frame1, const uint8_t *mask0, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int xPosition0, const unsigned int yPosition0, const Scalar xPosition1, const Scalar yPosition1, const unsigned int frame0PaddingElements, const unsigned int frame1PaddingElements, const unsigned int mask0PaddingElements, const unsigned int borderFactor)
Calculates the sum of square differences between two 5x5 frame regions in two frames with explicit we...
Definition: MappingF1.h:512
void applyMapping(Frame &frame, const Frame &mask, const unsigned int xStart, const unsigned int xWidth, const unsigned int yStart, const unsigned int yHeight, Worker *worker=nullptr) const override
Applies the current mapping for one given frame.
This class implements a mapping with float accuracy.
Definition: MappingF.h:30
Vector2 * mappingF_
Sub-pixel mappings for each pixel.
Definition: MappingF.h:137
MappingF & operator=(const MappingF &mappingObject)
Assign operator.
Definition: MappingF.h:240
unsigned int width_
Width of this pixel mapping object in pixel.
Definition: Mapping.h:147
unsigned int height_
Height of this pixel mapping object in pixel.
Definition: Mapping.h:150
This class implements a mapping with integer accuracy.
Definition: MappingI.h:30
static Caller< void > create(CT &object, typename MemberFunctionPointerMaker< CT, 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 member function with no function parameter.
Definition: Caller.h:3023
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
static constexpr int32_t round32(const T value)
Returns the rounded 32 bit integer value of a given value.
Definition: Numeric.h:2064
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition: base/Utilities.h:1029
float Scalar
Definition of a scalar type.
Definition: Math.h:128
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15