Ocean
Loading...
Searching...
No Matches
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
18namespace Ocean
19{
20
21namespace CV
22{
23
24namespace 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 */
48class 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
211template <unsigned int tChannels>
212inline 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
225template <unsigned int tChannels>
226inline 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
239template <unsigned int tChannels>
240inline 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
260inline MappingI1& MappingI1::operator=(const MappingI1& pixelMapping)
261{
262 MappingI::operator=(pixelMapping);
263 return *this;
264}
265
266inline MappingI1& MappingI1::operator=(MappingI1&& pixelMapping) noexcept
267{
268 if (this != &pixelMapping)
269 {
270 MappingI::operator=(pixelMapping);
271 }
272
273 return *this;
274}
275
276inline 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
411inline 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 {
444 return 0u;
445 }
446
447 // take the minimum cost only
448 if (localCost < cost)
449 {
450 cost = localCost;
451 }
452 }
453
454 // forward points one pixel to the right
455 ++targetMaskPointer;
456 ++mappingPointer;
457
458 // top pixel (north)
459 if (yTarget > 0 && *targetMaskPointer != 0xFF)
460 {
461 ocean_assert(*mappingPointer);
462 ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget]);
463 ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget]);
464
465 // topPosition - position = -1 (ideal)
466 // => topPosition - position + 1 => min
467 const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource + 1u);
468 ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) + 1));
469
470 // stop if we cannot get better
471 if (localCost == 0u)
472 {
473 return 0u;
474 }
475
476 // take the minimum cost only
477 if (localCost < cost)
478 {
479 cost = localCost;
480 }
481 }
482
483 // forward points one pixel to the right
484 ++targetMaskPointer;
485 ++mappingPointer;
486
487 // top right pixel (north east)
488 if (yTarget > 0 && xTarget + 1u < width_ && *targetMaskPointer != 0xFF)
489 {
490 ocean_assert(*mappingPointer);
491 ocean_assert(*mappingPointer == mappingI_[(yTarget - 1u) * width_ + xTarget + 1u]);
492 ocean_assert(*targetMaskPointer == targetMask[(yTarget - 1u) * targetMaskStrideElements + xTarget + 1u]);
493
494 // topPosition - position = -1 (ideal)
495 // => topPosition - position + 1 => min
496 // rightPosition - position = 1 (ideal)
497 // => rightPosition - position - 1 => min
498 const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource + 1u);
499
500 // stop if we cannot get better
501 if (localCost == 0u)
502 {
503 return 0u;
504 }
505
506 // take the minimum cost only
507 if (localCost < cost)
508 {
509 cost = localCost;
510 }
511 }
512
513 // forward pointers to next pixel position
514 ocean_assert(width_ >= 2u);
515 targetMaskPointer += targetMaskStrideElements - 2u;
516 mappingPointer += width_ - 2u;
517
518 // left pixel (west)
519 if (xTarget > 0 && *targetMaskPointer != 0xFF)
520 {
521 ocean_assert(*mappingPointer);
522 ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget - 1u]);
523 ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget - 1u]);
524
525 // leftPosition - position = -1 (ideal)
526 // => leftPosition - position + 1 => min
527 const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource);
528 ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) + 1) + sqr(int(mappingPointer->y()) - int(ySource)));
529
530 // stop if we cannot get better
531 if (localCost == 0u)
532 {
533 return 0u;
534 }
535
536 // take the minimum cost only
537 if (localCost < cost)
538 {
539 cost = localCost;
540 }
541 }
542
543 // forward pointers to next pixel position
544 targetMaskPointer += 2;
545 mappingPointer += 2;
546
547 // right pixel (east)
548 if (xTarget + 1 < width_ && *targetMaskPointer != 0xFF)
549 {
550 ocean_assert(*mappingPointer);
551 ocean_assert(*mappingPointer == mappingI_[yTarget * width_ + xTarget + 1u]);
552 ocean_assert(*targetMaskPointer == targetMask[yTarget * targetMaskStrideElements + xTarget + 1u]);
553
554 // rightPosition - position = 1 (ideal)
555 // => rightPosition - position - 1 => min
556 const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource);
557 ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource) - 1) + sqr(int(mappingPointer->y()) - int(ySource)));
558
559 // stop if we cannot get better
560 if (localCost == 0u)
561 {
562 return 0u;
563 }
564
565 // take the minimum cost only
566 if (localCost < cost)
567 {
568 cost = localCost;
569 }
570 }
571
572 // forward pointers to next pixel position
573 ocean_assert(width_ >= 2u);
574 targetMaskPointer += targetMaskStrideElements - 2u;
575 mappingPointer += width_ - 2u;
576
577 // bottom left pixel (south west)
578 if (xTarget > 0 && yTarget + 1 < height_ && * targetMaskPointer != 0xFF)
579 {
580 ocean_assert(*mappingPointer);
581 ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget - 1u]);
582 ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget - 1u]);
583
584 // bottomPosition - position = 1 (ideal)
585 // => bottomPosition - position - 1 => min
586 // leftPosition - position = -1 (ideal)
587 // => leftPosition - position + 1 => min
588 const unsigned int localCost = sqr(mappingPointer->x() - xSource + 1u) + sqr(mappingPointer->y() - ySource - 1u);
589
590 // stop if we cannot get better
591 if (localCost == 0u)
592 {
593 return 0u;
594 }
595
596 // take the minimum cost only
597 if (localCost < cost)
598 {
599 cost = localCost;
600 }
601 }
602
603 // forward points one pixel to the right
604 ++targetMaskPointer;
605 ++mappingPointer;
606
607 // bottom pixel (south)
608 if (yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
609 {
610 ocean_assert(*mappingPointer);
611 ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget]);
612 ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget]);
613
614 // bottomPosition - position = 1 (ideal)
615 // => bottomPosition - position - 1 => min
616 const unsigned int localCost = sqr(mappingPointer->x() - xSource) + sqr(mappingPointer->y() - ySource - 1u);
617 ocean_assert(localCost == sqr(int(mappingPointer->x()) - int(xSource)) + sqr(int(mappingPointer->y()) - int(ySource) - 1));
618
619 // stop if we cannot get better
620 if (localCost == 0u)
621 {
622 return 0u;
623 }
624
625 // take the minimum cost only
626 if (localCost < cost)
627 {
628 cost = localCost;
629 }
630 }
631
632 // forward points one pixel to the right
633 ++targetMaskPointer;
634 ++mappingPointer;
635
636 // bottom right pixel (south east)
637 if (xTarget + 1 < width_ && yTarget + 1 < height_ && *targetMaskPointer != 0xFF)
638 {
639 ocean_assert(*mappingPointer);
640 ocean_assert(*mappingPointer == mappingI_[(yTarget + 1u) * width_ + xTarget + 1u]);
641 ocean_assert(*targetMaskPointer == targetMask[(yTarget + 1u) * targetMaskStrideElements + xTarget + 1u]);
642
643 // bottomPosition - position = 1 (ideal)
644 // => bottomPosition - position - 1 => min
645 // leftPosition - position = -1 (ideal)
646 // => leftPosition - position + 1 => min
647 const unsigned int localCost = sqr(mappingPointer->x() - xSource - 1u) + sqr(mappingPointer->y() - ySource - 1u);
648
649 // stop if we cannot get better
650 if (localCost == 0u)
651 {
652 return 0u;
653 }
654
655 // take the minimum cost only
656 if (localCost < cost)
657 {
658 cost = localCost;
659 }
660 }
661
662 return cost;
663}
664
665template <unsigned int tChannels, unsigned int tBorderFactor>
666unsigned 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
667{
668 static_assert(tChannels >= 1u, "Invalid channel number!");
669 static_assert(tBorderFactor >= 1u, "Invalid border factor!");
670
671 ocean_assert(mask != nullptr && frame != nullptr);
672
673 ocean_assert(xTarget < width_ && yTarget < height_);
674 ocean_assert(xSource < width_ && ySource < height_);
675
676 const unsigned int maskStrideElements = width_ + maskPaddingElements;
677
678 // the given in-coordinate must lie inside the completion mask
679 ocean_assert(mask[yTarget * maskStrideElements + xTarget] != 0xFF);
680 // the given out-coordinate must lie outside the completion mask
681 ocean_assert(mask[ySource * maskStrideElements + xSource] == 0xFF);
682
683 ocean_assert(width_ >= 3u);
684 ocean_assert(height_ >= 3u);
685
686 if (xSource >= 2 && ySource >= 2 && xSource + 2 < width_ && ySource + 2 < height_)
687 {
688 if (mask[yTarget * maskStrideElements + xTarget] == 0x00 || mask[yTarget * maskStrideElements + xTarget] >= 3)
689 {
690 ocean_assert(xTarget >= 2 && yTarget >= 2 && xTarget + 2 < width_ && yTarget + 2 < height_);
691 return Advanced::SumSquareDifferencesNoCenter::patch8BitPerChannel<tChannels, 5u>(frame, frame, width_, width_, xTarget, yTarget, xSource, ySource, framePaddingElements, framePaddingElements) * spatialCostNormalization<tChannels>() / 25u;
692 }
693
694 if (xTarget >= 2 && yTarget >= 2 && xTarget + 2 < width_ && yTarget + 2 < height_)
695 {
696 const unsigned int frameStrideElements = width_ * tChannels + framePaddingElements;
697
698 const uint8_t* const frameTargetTopLeft = frame + (yTarget - 2) * frameStrideElements + (xTarget - 2) * tChannels;
699 const uint8_t* const frameSourceTopLeft = frame + (ySource - 2) * frameStrideElements + (xSource - 2) * tChannels;
700 const uint8_t* const maskTopLeft = mask + (yTarget - 2) * maskStrideElements + xTarget - 2;
701
702 return ssd5x5MaskNoCenter<tChannels, tBorderFactor>(frameTargetTopLeft, frameSourceTopLeft, maskTopLeft, width_, width_, framePaddingElements, framePaddingElements, maskPaddingElements) * spatialCostNormalization<tChannels>() / 25u;
703 }
704 }
705
706 unsigned int cost = 0;
707
708 int iterOutX = int(xSource) - 2;
709 for (int iterInX = int(xTarget) - 2; iterInX <= int(xTarget) + 2; ++iterInX)
710 {
711 const unsigned int validIterInX = mirrorValue(iterInX, width_);
712 const unsigned int validIterOutX = mirrorValue(iterOutX, width_);
713
714 int iterOutY = int(ySource) - 2;
715 for (int iterInY = int(yTarget) - 2; iterInY <= int(yTarget) + 2; ++iterInY)
716 {
717 if (iterInX != int(xTarget) || iterInY != int(yTarget))
718 {
719 const unsigned int validIterInY = mirrorValue(iterInY, height_);
720 const unsigned int validIterOutY = mirrorValue(iterOutY, height_);
721
722 ocean_assert(mask[validIterInY * maskStrideElements + validIterInX] + 1 > 0);
723
724 if (mask[validIterInY * maskStrideElements + validIterInX] != 0xFF)
725 {
726 cost += CV::SumSquareDifferences::patch8BitPerChannelTemplate<tChannels, 1u>(frame, frame, width_, width_, validIterInX, validIterInY, validIterOutX, validIterOutY, framePaddingElements, framePaddingElements);
727 }
728 else
729 {
730 cost += CV::SumSquareDifferences::patch8BitPerChannelTemplate<tChannels, 1u>(frame, frame, width_, width_, validIterInX, validIterInY, validIterOutX, validIterOutY, framePaddingElements, framePaddingElements) * tBorderFactor;
731 }
732 }
733
734 ++iterOutY;
735 }
736
737 ++iterOutX;
738 }
739
740 return cost * spatialCostNormalization<tChannels>() / 25u;
741}
742
743template <unsigned int tChannels>
744void 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
745{
746 static_assert(tChannels >= 1u, "Invalid channels!");
747
749
750 ocean_assert(xStart + xWidth <= width_);
751 ocean_assert(firstRow + numberRows <= height_);
752
753 ocean_assert(frameStrideElements >= width_ * tChannels);
754 ocean_assert(maskStrideElements >= width_);
755
756 for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
757 {
758 DataType* framePixel = ((DataType*)(frame + y * frameStrideElements)) + xStart;
759 const uint8_t* maskPixel = mask + y * maskStrideElements + xStart;
760
761 const CV::PixelPosition* mappingPixel = mappingI_ + y * width_ + xStart; // mapping does not contain padding (mappingStride == width_)
762
763 for (unsigned int n = 0u; n < xWidth; ++n)
764 {
765 if (*maskPixel != 0xFF)
766 {
767 ocean_assert(mappingPixel->isValid());
768
769 *framePixel = ((const DataType*)(frame + mappingPixel->y() * frameStrideElements))[mappingPixel->x()];
770 }
771
772 ++framePixel;
773 ++maskPixel;
774
775 ++mappingPixel;
776 }
777 }
778}
779
780}
781
782}
783
784}
785
786#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:468
T x() const
Returns the horizontal coordinate position of this object.
Definition PixelPosition.h:456
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:666
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:744
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:3024
Template class allowing to define an array of data types.
Definition DataType.h:27
This class implements Ocean's image class.
Definition Frame.h:1879
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:1099
static unsigned int mirrorValue(const int value, const unsigned int size)
Mirrors a given value if necessary.
Definition base/Utilities.h:1277
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Default definition of a type with tBytes bytes.
Definition DataType.h:32