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