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