Ocean
MappingI1.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_I_1_H
9 #define META_OCEAN_CV_SYNTHESIS_MAPPING_I_1_H
10 
13 
14 #include "ocean/base/Worker.h"
15 
17 
18 namespace Ocean
19 {
20 
21 namespace CV
22 {
23 
24 namespace Synthesis
25 {
26 
27 /**
28  * This class implements the pixel mapping between source and target frames.
29  *
30  * Cost function:<br>
31  *
32  * pixelCost = spatialFactor * spatialCost + appearanceCost<br>
33  *
34  * spatialCost = spatialCost' / normalizationSpatialCost<br>
35  * appearanceCost = appearanceCost' / normalizationAppearanceCost<br>
36  *
37  * spatialCost<br>
38  * pixelCost = spatialFactor * spatialCost' / normalizationSpatialCost + appearanceCost' / normalizationAppearanceCost<br>
39  *
40  * pixelCost' = spatialFactor * spatialCost * normalizationAppearanceCost + appearanceCost * normalizationSpatialCost<br>
41  *
42  * 24bit:<br>
43  * normalizationAppearanceCost = 3 * 255^2 * numberSamples<br>
44  * normalizationSpatialCost = width^2 + height^2<br>
45  *
46  * @ingroup cvsynthesis
47  */
48 class OCEAN_CV_SYNTHESIS_EXPORT MappingI1 : public MappingI
49 {
50  public:
51 
52  /**
53  * Creates an empty mapping object.
54  */
56 
57  /**
58  * Copies a mapping from a given mapping object.
59  * @param pixelMapping Pixel mapping to be copied
60  */
61  MappingI1(const MappingI1& pixelMapping);
62 
63  /**
64  * Move constructor.
65  * @param pixelMapping Mapping to be moved
66  */
67  MappingI1(MappingI1&& pixelMapping) noexcept;
68 
69  /**
70  * Creates a new mapping object with defined dimension.
71  * An initial mapping is not provided.<br>
72  * @param width The width of the mapping object in pixel, with range [1, infinity)
73  * @param height The height of the mapping object in pixel, with range [1, infinity)
74  */
75  MappingI1(const unsigned int width, const unsigned int height);
76 
77  /**
78  * Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood and normalizes the result according to the frame dimension.
79  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
80  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width - 1], and must lie inside the target mask
81  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height - 1], and must lie inside the target mask
82  * @param xSource Corresponding horizontal source mapping position for the given position
83  * @param ySource Corresponding vertical source mapping position for the given position
84  * @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
85  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
86  * @param maxCost The maximal cost the spatial cost can have, with range [1, infinity)
87  * @return Resulting spatial cost for the given points
88  * @tparam tChannels The number of data channels of the frame, with range [1, infinity)
89  * @see spatialCost8Neighborhood().
90  */
91  template <unsigned int tChannels>
92  inline unsigned int spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const;
93 
94  /**
95  * Calculates the smallest/cheapest spatial cost for a given point in a eight-neighborhood and normalizes the result according to the frame dimension.
96  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
97  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width) and must lie inside the target mask
98  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height) and must lie inside the target mask
99  * @param xSource Corresponding horizontal source mapping position for the given position
100  * @param ySource Corresponding vertical source mapping position for the given position
101  * @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
102  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
103  * @param maxCost The maximal cost the spatial cost can have, with range [1, infinity)
104  * @return Resulting spatial cost for the given points
105  * @tparam tChannels The number of data channels of the frame, with range [1, infinity)
106  * @see spatialCost8Neighborhood().
107  */
108  template <unsigned int tChannels>
109  inline unsigned int spatialCost8Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const;
110 
111  /**
112  * Calculates the appearance cost for a given point in a given frame.
113  * @param xTarget Horizontal target position to determine the appearance cost for, with range [0, width) and must lie inside the target mask
114  * @param yTarget Vertical target position to determine the appearance cost for, with range [0, height) and must lie inside the target mask
115  * @param xSource Horizontal source position to determine the appearance cost for, with range [0, width) and must lie outside the target mask
116  * @param ySource Vertical source position to determine the appearance cost for, with range [0, height) and must lie outside the target mask
117  * @param frame The target and source frame to determine the appearance cost on, with same dimension as this mapping object
118  * @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
119  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
120  * @param maskPaddingElements The number f padding elements at the end of each mask row, in elements, with range [0, infinity)
121  * @tparam tChannels The number of channels of the frame, with range [1, infinity)
122  * @tparam tBorderFactor Constant factor to weight the appearance cost of synthesis border pixels (border between target and source pixels) individually, with range [1, infinity)
123  */
124  template <unsigned int tChannels, unsigned int tBorderFactor>
125  unsigned int appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements) const;
126 
127  /**
128  * Applies the current mapping for one given frame.<br>
129  * @see Mapping::applyMapping().
130  */
131  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;
132 
133  /**
134  * Applies the current mapping for one given frame.<br>
135  * 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.
136  * @param frame The frame holding source and target area
137  * @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
138  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
139  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
140  * @param xStart Horizontal start position of the update area in pixel, with range [0, width())
141  * @param xWidth Width of the update area in pixel, with range [1, width() - xStart]
142  * @param yStart Vertical start position of the update area in pixel, with range [0, height())
143  * @param yHeight Height of the update area in pixel, with range [1, height() - yStart]
144  * @param worker Optional worker object to distribute the computation
145  * @tparam tChannels Number of data channels of the frame, with range [1, infinity)
146  */
147  template <unsigned int tChannels>
148  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;
149 
150  /**
151  * Assigns another pixel mapping object to this one.
152  * @param pixelMapping Pixel mapping object to be copied
153  * @return Reference to this object
154  */
155  inline MappingI1& operator=(const MappingI1& pixelMapping);
156 
157  /**
158  * Move operator.
159  * @param pixelMapping Right mapping to moved
160  * @return Reference to this move
161  */
162  inline MappingI1& operator=(MappingI1&& pixelMapping) noexcept;
163 
164  private:
165 
166  /**
167  * Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood.
168  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
169  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width) and must lie inside the target mask
170  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height) and must lie inside the target mask
171  * @param xSource Corresponding horizontal source mapping position for the given position
172  * @param ySource Corresponding vertical source mapping position for the given position
173  * @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
174  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
175  * @param maxCost The maximal cost the spatial cost can have, with range [1, infinity)
176  * @return Resulting spatial cost for the given points
177  */
178  inline unsigned int spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const;
179 
180  /**
181  * Calculates the smallest/cheapest spatial cost for a given point in a eight-neighborhood.
182  * Instead of summing ob the cost for all neighboring pixels, this function determines the minimal cost of all neighboring pixels.
183  * @param xTarget Horizontal target position to determine the spatial cost for, with range [0, width) and must lie inside the target mask
184  * @param yTarget Vertical target position to determine the spatial cost for, with range [0, height) and must lie inside the target mask
185  * @param xSource Corresponding horizontal source mapping position for the given position
186  * @param ySource Corresponding vertical source mapping position for the given position
187  * @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
188  * @param targetMaskPaddingElements The number of padding elements at the end of each target mask row, in elements, with range [0, infinity)
189  * @param maxCost The maximal cost the spatial cost can have, with range [1, infinity)
190  * @return Resulting spatial cost for the given points
191  */
192  inline unsigned int spatialCost8Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const;
193 
194  /**
195  * Applies the current mapping in a subset of one given frame.<br>
196  * 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.
197  * @param frame The frame holding source and target area, with frame dimension identical to width() x height()
198  * @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
199  * @param frameStrideElements The number of elements between two frame rows, in elements, with range [width * tChannels, infinity)
200  * @param maskStrideElements The number of elements between two frame rows, in elements, with range [width, infinity)
201  * @param xStart Horizontal start position of the update area in pixel, with range [0, width())
202  * @param xWidth Width of the update area in pixel, with range [1, width() - xStart]
203  * @param firstRow The first row to be handled, with range [0, height())
204  * @param numberRows The number of rows to be handled, with range [1, height() - yStart]
205  * @tparam tChannels Number of data channels of the frame, with range [1, infinity)
206  */
207  template <unsigned int tChannels>
208  void applyOneFrameMapping8BitPerChannelSubset(uint8_t* const frame, const uint8_t* const mask, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int firstRow, const unsigned int numberRows) const;
209 };
210 
211 template <unsigned int tChannels>
212 inline unsigned int MappingI1::spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
213 {
214  const unsigned int cost = spatialCost4Neighborhood(xTarget, yTarget, xSource, ySource, targetMask, targetMaskPaddingElements, maxCost);
215 
216  ocean_assert(cost <= maxCost);
217  if (cost == maxCost)
218  {
219  return maxCost;
220  }
221 
222  return cost * appearanceCostNormalization<tChannels>();
223 }
224 
225 template <unsigned int tChannels>
226 inline unsigned int MappingI1::spatialCost8Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
227 {
228  const unsigned int cost = spatialCost8Neighborhood(xTarget, yTarget, xSource, ySource, targetMask, targetMaskPaddingElements, maxCost);
229 
230  ocean_assert(cost <= maxCost);
231  if (cost == maxCost)
232  {
233  return maxCost;
234  }
235 
236  return cost * appearanceCostNormalization<tChannels>();
237 }
238 
239 template <unsigned int tChannels>
240 inline void MappingI1::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
241 {
242  ocean_assert(frame != nullptr && mask != nullptr);
243 
244  ocean_assert(xStart + xWidth <= width_);
245  ocean_assert(yStart + yHeight <= height_);
246 
247  const unsigned int frameStrideElements = width_ * tChannels + framePaddingElements;
248  const unsigned int maskStrideElements = width_ + maskPaddingElements;
249 
250  if (worker)
251  {
252  worker->executeFunction(Worker::Function::create(*this, &MappingI1::applyOneFrameMapping8BitPerChannelSubset<tChannels>, frame, mask, frameStrideElements, maskStrideElements, xStart, xWidth, 0u, 0u), yStart, yHeight, 6u, 7u, 40u);
253  }
254  else
255  {
256  applyOneFrameMapping8BitPerChannelSubset<tChannels>(frame, mask, frameStrideElements, maskStrideElements, xStart, xWidth, yStart, yHeight);
257  }
258 }
259 
260 inline MappingI1& MappingI1::operator=(const MappingI1& pixelMapping)
261 {
262  MappingI::operator=(pixelMapping);
263  return *this;
264 }
265 
266 inline MappingI1& MappingI1::operator=(MappingI1&& pixelMapping) noexcept
267 {
268  if (this != &pixelMapping)
269  {
270  MappingI::operator=(pixelMapping);
271  }
272 
273  return *this;
274 }
275 
276 inline unsigned int MappingI1::spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
277 {
278  ocean_assert(targetMask != nullptr);
279  ocean_assert(maxCost > 0u);
280 
281  // target position must fit to the layer dimensions
282  ocean_assert(xTarget < width_ && yTarget < height_);
283 
284  const unsigned int targetMaskStrideElements = width_ + targetMaskPaddingElements;
285 
286  // the given in-coordinate must lie inside the completion mask
287  ocean_assert(targetMask[yTarget * targetMaskStrideElements + xTarget] != 0xFF);
288 
289  unsigned int cost = maxCost;
290 
291  // north pixel is start position
292  const uint8_t* targetMaskPointer = targetMask + (int(yTarget) - 1) * int(targetMaskStrideElements) + xTarget;
293  const PixelPosition* mappingPointer = mappingI_ + (int(yTarget) - 1) * int(width_) + xTarget;
294 
295  // top pixel (north)
296  if (yTarget > 0u && *targetMaskPointer != 0xFF)
297  {
298  ocean_assert(*mappingPointer);
299  ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget]);
300  ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget]);
301 
302  // topPosition - position = -1 (ideal)
303  // => topPosition - position + 1 => min
304  const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource + 1u);
305  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) + 1));
306 
307  // stop if we cannot get better
308  if (localCost == 0u)
309  {
310  return 0u;
311  }
312 
313  // take the minimum cost only
314  if (localCost < cost)
315  {
316  cost = localCost;
317  }
318  }
319 
320  // forward pointers to next pixel position
321  ocean_assert(width_ >= 1u);
322  targetMaskPointer += targetMaskStrideElements - 1u;
323  mappingPointer += width_ - 1u;
324 
325  // left pixel (west)
326  if (xTarget > 0 && *targetMaskPointer != 0xFF)
327  {
328  ocean_assert(*mappingPointer);
329  ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget - 1u]);
330  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget - 1u]);
331 
332  // leftPosition - position = -1 (ideal)
333  // => leftPosition - position + 1 => min
334  const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource);
335  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) + 1) + sqr(int(mappingPointer->y()) - int(ySource)));
336 
337  // stop if we cannot get better
338  if (localCost == 0u)
339  {
340  return 0u;
341  }
342 
343  // take the minimum cost only
344  if (localCost < cost)
345  {
346  cost = localCost;
347  }
348  }
349 
350  // forward pointers to next pixel position
351  targetMaskPointer += 2;
352  mappingPointer += 2;
353 
354  // right pixel (east)
355  if (xTarget + 1 < width_ && *targetMaskPointer != 0xFF)
356  {
357  ocean_assert(*mappingPointer);
358  ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget + 1u]);
359  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget + 1u]);
360 
361  // rightPosition - position = 1 (ideal)
362  // => rightPosition - position - 1 => min
363  const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource);
364  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) - 1) + sqr(int(mappingPointer->y()) - int(ySource)));
365 
366  // stop if we cannot get better
367  if (localCost == 0u)
368  {
369  return 0u;
370  }
371 
372  // take the minimum cost only
373  if (localCost < cost)
374  {
375  cost = localCost;
376  }
377  }
378 
379  // forward points one pixel to the right
380  targetMaskPointer += targetMaskStrideElements - 1u;
381  mappingPointer += width_ - 1u;
382 
383  // bottom pixel (south)
384  if (yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
385  {
386  ocean_assert(*mappingPointer);
387  ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget]);
388  ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget]);
389 
390  // bottomPosition - position = 1 (ideal)
391  // => bottomPosition - position - 1 => min
392  const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource - 1u);
393  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) - 1));
394 
395  // stop if we cannot get better
396  if (localCost == 0u)
397  {
398  return 0u;
399  }
400 
401  // take the minimum cost only
402  if (localCost < cost)
403  {
404  cost = localCost;
405  }
406  }
407 
408  return cost;
409 }
410 
411 inline unsigned int MappingI1::spatialCost8Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
412 {
413  ocean_assert(targetMask);
414 
415  // target position must fit to the layer dimensions
416  ocean_assert(xTarget < width_ && yTarget < height_);
417 
418  const unsigned int targetMaskStrideElements = width_ + targetMaskPaddingElements;
419 
420  // the given in-coordinate must lie inside the completion mask
421  ocean_assert(targetMask[yTarget * targetMaskStrideElements + xTarget] != 0xFF);
422 
423  unsigned int cost = maxCost;
424 
425  const uint8_t* targetMaskPointer = targetMask + (int(yTarget) - 1) * int(targetMaskStrideElements) + xTarget - 1;
426  const PixelPosition* mappingPointer = mappingI_ + (int(yTarget) - 1) * int(width_) + xTarget - 1;
427 
428  // top left pixel (north west)
429  if (yTarget > 0 && xTarget > 0 && *targetMaskPointer != 0xFF)
430  {
431  ocean_assert(*mappingPointer);
432  ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget - 1u]);
433  ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget - 1u]);
434 
435  // topPosition - position = -1 (ideal)
436  // => topPosition - position + 1 => min
437  // leftPosition - position = -1 (ideal)
438  // => leftPosition - position + 1 => min
439  const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource + 1u);
440 
441  // stop if we cannot get better
442  if (localCost == 0u)
443  return 0u;
444 
445  // take the minimum cost only
446  if (localCost < cost)
447  cost = localCost;
448  }
449 
450  // forward points one pixel to the right
451  ++targetMaskPointer;
452  ++mappingPointer;
453 
454  // top pixel (north)
455  if (yTarget > 0 && *targetMaskPointer != 0xFF)
456  {
457  ocean_assert(*mappingPointer);
458  ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget]);
459  ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget]);
460 
461  // topPosition - position = -1 (ideal)
462  // => topPosition - position + 1 => min
463  const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource + 1u);
464  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) + 1));
465 
466  // stop if we cannot get better
467  if (localCost == 0u)
468  return 0u;
469 
470  // take the minimum cost only
471  if (localCost < cost)
472  cost = localCost;
473  }
474 
475  // forward points one pixel to the right
476  ++targetMaskPointer;
477  ++mappingPointer;
478 
479  // top right pixel (north east)
480  if (yTarget > 0 && xTarget + 1u < width_ && *targetMaskPointer != 0xFF)
481  {
482  ocean_assert(*mappingPointer);
483  ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget + 1u]);
484  ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget + 1u]);
485 
486  // topPosition - position = -1 (ideal)
487  // => topPosition - position + 1 => min
488  // rightPosition - position = 1 (ideal)
489  // => rightPosition - position - 1 => min
490  const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource + 1u);
491 
492  // stop if we cannot get better
493  if (localCost == 0u)
494  return 0u;
495 
496  // take the minimum cost only
497  if (localCost < cost)
498  cost = localCost;
499  }
500 
501  // forward pointers to next pixel position
502  ocean_assert(width_ >= 2u);
503  targetMaskPointer += targetMaskStrideElements - 2u;
504  mappingPointer += width_ - 2u;
505 
506  // left pixel (west)
507  if (xTarget > 0 && *targetMaskPointer != 0xFF)
508  {
509  ocean_assert(*mappingPointer);
510  ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget - 1u]);
511  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget - 1u]);
512 
513  // leftPosition - position = -1 (ideal)
514  // => leftPosition - position + 1 => min
515  const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource);
516  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) + 1) + sqr(int(mappingPointer->y()) - int(ySource)));
517 
518  // stop if we cannot get better
519  if (localCost == 0u)
520  return 0u;
521 
522  // take the minimum cost only
523  if (localCost < cost)
524  cost = localCost;
525  }
526 
527  // forward pointers to next pixel position
528  targetMaskPointer += 2;
529  mappingPointer += 2;
530 
531  // right pixel (east)
532  if (xTarget + 1 < width_ && *targetMaskPointer != 0xFF)
533  {
534  ocean_assert(*mappingPointer);
535  ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget + 1u]);
536  ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget + 1u]);
537 
538  // rightPosition - position = 1 (ideal)
539  // => rightPosition - position - 1 => min
540  const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource);
541  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) - 1) + sqr(int(mappingPointer->y()) - int(ySource)));
542 
543  // stop if we cannot get better
544  if (localCost == 0u)
545  return 0u;
546 
547  // take the minimum cost only
548  if (localCost < cost)
549  cost = localCost;
550  }
551 
552  // forward pointers to next pixel position
553  ocean_assert(width_ >= 2u);
554  targetMaskPointer += targetMaskStrideElements - 2u;
555  mappingPointer += width_ - 2u;
556 
557  // bottom left pixel (south west)
558  if (xTarget > 0 && yTarget + 1 < height_ && * targetMaskPointer != 0xFF)
559  {
560  ocean_assert(*mappingPointer);
561  ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget - 1u]);
562  ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget - 1u]);
563 
564  // bottomPosition - position = 1 (ideal)
565  // => bottomPosition - position - 1 => min
566  // leftPosition - position = -1 (ideal)
567  // => leftPosition - position + 1 => min
568  const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource - 1u);
569 
570  // stop if we cannot get better
571  if (localCost == 0u)
572  return 0u;
573 
574  // take the minimum cost only
575  if (localCost < cost)
576  cost = localCost;
577  }
578 
579  // forward points one pixel to the right
580  ++targetMaskPointer;
581  ++mappingPointer;
582 
583  // bottom pixel (south)
584  if (yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
585  {
586  ocean_assert(*mappingPointer);
587  ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget]);
588  ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget]);
589 
590  // bottomPosition - position = 1 (ideal)
591  // => bottomPosition - position - 1 => min
592  const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource - 1u);
593  ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) - 1));
594 
595  // stop if we cannot get better
596  if (localCost == 0u)
597  return 0u;
598 
599  // take the minimum cost only
600  if (localCost < cost)
601  cost = localCost;
602  }
603 
604  // forward points one pixel to the right
605  ++targetMaskPointer;
606  ++mappingPointer;
607 
608  // bottom right pixel (south east)
609  if (xTarget + 1 < width_ && yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
610  {
611  ocean_assert(*mappingPointer);
612  ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget + 1u]);
613  ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget + 1u]);
614 
615  // bottomPosition - position = 1 (ideal)
616  // => bottomPosition - position - 1 => min
617  // leftPosition - position = -1 (ideal)
618  // => leftPosition - position + 1 => min
619  const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource - 1u);
620 
621  // stop if we cannot get better
622  if (localCost == 0u)
623  return 0u;
624 
625  // take the minimum cost only
626  if (localCost < cost)
627  cost = localCost;
628  }
629 
630  return cost;
631 }
632 
633 template <unsigned int tChannels, unsigned int tBorderFactor>
634 unsigned int MappingI1::appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t* frame, const uint8_t* mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements) const
635 {
636  static_assert(tChannels >= 1u, "Invalid channel number!");
637  static_assert(tBorderFactor >= 1u, "Invalid border factor!");
638 
639  ocean_assert(mask != nullptr && frame != nullptr);
640 
641  ocean_assert(xTarget < width_ && yTarget < height_);
642  ocean_assert(xSource < width_ && ySource < height_);
643 
644  const unsigned int maskStrideElements = width_ + maskPaddingElements;
645 
646  // the given in-coordinate must lie inside the completion mask
647  ocean_assert(mask[yTarget * maskStrideElements + xTarget] != 0xFF);
648  // the given out-coordinate must lie outside the completion mask
649  ocean_assert(mask[ySource * maskStrideElements + xSource] == 0xFF);
650 
651  ocean_assert(width_ >= 3u);
652  ocean_assert(height_ >= 3u);
653 
654  if (xSource >= 2 && ySource >= 2 && xSource + 2 < width_ && ySource + 2 < height_)
655  {
656  if (mask[yTarget * maskStrideElements + xTarget] == 0x00 || mask[yTarget * maskStrideElements + xTarget] >= 3)
657  {
658  ocean_assert(xTarget >= 2 && yTarget >= 2 && xTarget + 2 < width_ && yTarget + 2 < height_);
659  return Advanced::SumSquareDifferencesNoCenter::patch8BitPerChannel<tChannels, 5u>(frame, frame, width_, width_, xTarget, yTarget, xSource, ySource, framePaddingElements, framePaddingElements) * spatialCostNormalization<tChannels>() / 25u;
660  }
661 
662  if (xTarget >= 2 && yTarget >= 2 && xTarget + 2 < width_ && yTarget + 2 < height_)
663  {
664  const unsigned int frameStrideElements = width_ * tChannels + framePaddingElements;
665 
666  const uint8_t* const frameTargetTopLeft = frame + (yTarget - 2) * frameStrideElements + (xTarget - 2) * tChannels;
667  const uint8_t* const frameSourceTopLeft = frame + (ySource - 2) * frameStrideElements + (xSource - 2) * tChannels;
668  const uint8_t* const maskTopLeft = mask + (yTarget - 2) * maskStrideElements + xTarget - 2;
669 
670  return ssd5x5MaskNoCenter<tChannels, tBorderFactor>(frameTargetTopLeft, frameSourceTopLeft, maskTopLeft, width_, width_, framePaddingElements, framePaddingElements, maskPaddingElements) * spatialCostNormalization<tChannels>() / 25u;
671  }
672  }
673 
674  unsigned int cost = 0;
675 
676  int iterOutX = int(xSource) - 2;
677  for (int iterInX = int(xTarget) - 2; iterInX <= int(xTarget) + 2; ++iterInX)
678  {
679  const unsigned int validIterInX = mirrorValue(iterInX, width_);
680  const unsigned int validIterOutX = mirrorValue(iterOutX, width_);
681 
682  int iterOutY = int(ySource) - 2;
683  for (int iterInY = int(yTarget) - 2; iterInY <= int(yTarget) + 2; ++iterInY)
684  {
685  if (iterInX != int(xTarget) || iterInY != int(yTarget))
686  {
687  const unsigned int validIterInY = mirrorValue(iterInY, height_);
688  const unsigned int validIterOutY = mirrorValue(iterOutY, height_);
689 
690  ocean_assert(mask[validIterInY * maskStrideElements + validIterInX] + 1 > 0);
691 
692  if (mask[validIterInY * maskStrideElements + validIterInX] != 0xFF)
693  {
694  cost += CV::SumSquareDifferences::patch8BitPerChannelTemplate<tChannels, 1u>(frame, frame, width_, width_, validIterInX, validIterInY, validIterOutX, validIterOutY, framePaddingElements, framePaddingElements);
695  }
696  else
697  {
698  cost += CV::SumSquareDifferences::patch8BitPerChannelTemplate<tChannels, 1u>(frame, frame, width_, width_, validIterInX, validIterInY, validIterOutX, validIterOutY, framePaddingElements, framePaddingElements) * tBorderFactor;
699  }
700  }
701 
702  ++iterOutY;
703  }
704 
705  ++iterOutX;
706  }
707 
708  return cost * spatialCostNormalization<tChannels>() / 25u;
709 }
710 
711 template <unsigned int tChannels>
712 void MappingI1::applyOneFrameMapping8BitPerChannelSubset(uint8_t* const frame, const uint8_t* const mask, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int xStart, const unsigned int xWidth, const unsigned int firstRow, const unsigned int numberRows) const
713 {
714  static_assert(tChannels >= 1u, "Invalid channels!");
715 
717 
718  ocean_assert(xStart + xWidth <= width_);
719  ocean_assert(firstRow + numberRows <= height_);
720 
721  ocean_assert(frameStrideElements >= width_ * tChannels);
722  ocean_assert(maskStrideElements >= width_);
723 
724  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
725  {
726  DataType* framePixel = ((DataType*)(frame + y * frameStrideElements)) + xStart;
727  const uint8_t* maskPixel = mask + y * maskStrideElements + xStart;
728 
729  const CV::PixelPosition* mappingPixel = mappingI_ + y * width_ + xStart; // mapping does not contain padding (mappingStride == width_)
730 
731  for (unsigned int n = 0u; n < xWidth; ++n)
732  {
733  if (*maskPixel != 0xFF)
734  {
735  ocean_assert(mappingPixel->isValid());
736 
737  *framePixel = ((const DataType*)(frame + mappingPixel->y() * frameStrideElements))[mappingPixel->x()];
738  }
739 
740  ++framePixel;
741  ++maskPixel;
742 
743  ++mappingPixel;
744  }
745  }
746 }
747 
748 }
749 
750 }
751 
752 }
753 
754 #endif // META_OCEAN_CV_SYNTHESIS_MAPPING_I_1_H
bool isValid() const
Returns whether this pixel position object holds two valid parameters.
T y() const
Returns the vertical coordinate position of this object.
Definition: PixelPosition.h:470
T x() const
Returns the horizontal coordinate position of this object.
Definition: PixelPosition.h:458
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 the pixel mapping between source and target frames.
Definition: MappingI1.h:49
MappingI1()
Creates an empty mapping object.
unsigned int spatialCost4Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t *targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
Calculates the smallest/cheapest spatial cost for a given point in a four-neighborhood and normalizes...
Definition: MappingI1.h:212
MappingI1 & operator=(const MappingI1 &pixelMapping)
Assigns another pixel mapping object to this one.
Definition: MappingI1.h:260
unsigned int spatialCost8Neighborhood(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t *targetMask, const unsigned int targetMaskPaddingElements, const unsigned int maxCost) const
Calculates the smallest/cheapest spatial cost for a given point in a eight-neighborhood and normalize...
Definition: MappingI1.h:226
unsigned int appearanceCost5x5(const unsigned int xTarget, const unsigned int yTarget, const unsigned int xSource, const unsigned int ySource, const uint8_t *frame, const uint8_t *mask, const unsigned int framePaddingElements, const unsigned int maskPaddingElements) const
Calculates the appearance cost for a given point in a given frame.
Definition: MappingI1.h:634
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.
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: MappingI1.h:240
MappingI1(const MappingI1 &pixelMapping)
Copies a mapping from a given mapping object.
void applyOneFrameMapping8BitPerChannelSubset(uint8_t *const frame, const uint8_t *const mask, const unsigned int frameStrideElements, const unsigned int maskStrideElements, 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: MappingI1.h:712
MappingI1(const unsigned int width, const unsigned int height)
Creates a new mapping object with defined dimension.
MappingI1(MappingI1 &&pixelMapping) noexcept
Move constructor.
This class implements a mapping with integer accuracy.
Definition: MappingI.h:30
MappingI & operator=(const MappingI &pixelMapping)
Assign operator.
Definition: MappingI.h:321
PixelPosition * mappingI_
Pixel mappings for each pixel.
Definition: MappingI.h:171
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:1792
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
static unsigned int mirrorValue(const int value, const unsigned int size)
Mirrors a given value if necessary.
Definition: base/Utilities.h:1207
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15