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 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
633template <unsigned int tChannels, unsigned int tBorderFactor>
634unsigned 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
711template <unsigned int tChannels>
712void 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:1808
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
Default definition of a type with tBytes bytes.
Definition DataType.h:32