Ocean
ContourMapping.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_SEGMENTATION_CONTOUR_MAPPING_H
9 #define META_OCEAN_CV_SEGMENTATION_CONTOUR_MAPPING_H
10 
13 
14 #include "ocean/base/Frame.h"
16 #include "ocean/base/RandomI.h"
17 
18 #include "ocean/cv/Bresenham.h"
20 #include "ocean/cv/PixelPosition.h"
22 
23 namespace Ocean
24 {
25 
26 namespace CV
27 {
28 
29 namespace Segmentation
30 {
31 
32 /**
33  * This class determines mappings between pixels lying on a contour.
34  * @ingroup cvsegmentation
35  */
36 class OCEAN_CV_SEGMENTATION_EXPORT ContourMapping
37 {
38  public:
39 
40  /**
41  * Determines the mapping between pixels lying on a contour (defined within a frame) based on visual and geometrical constraints.
42  * The resulting mapping pairs (bidirectionally) pixels on the contour that seem to have the same characteristics regarding visual or geometrical conditions.<br>
43  * Further, the resulting mapping will contain mapping between contour pixels so that the line between those pixels do not leave the mask area.
44  * @param frame The frame in which the contour is defined, must be valid
45  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
46  * @param width The width of the provided frame (and mask) in pixel, with range [1, infinity)
47  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
48  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
49  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
50  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
51  * @return The resulting mapping for each pixel of the provided contour, for each (source) contour pixel the index of the corresponding (target) contour pixel will be provided, an index of -1 identifies pixels without corresponding pixel
52  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
53  * @see mappingInterpolation8BitPerChannel().
54  */
55  template <unsigned int tChannels>
56  static Indices32 contour2mapping8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions& denseContour);
57 
58  /**
59  * Replaces the visual content of a frame within a mask area by using the mapping information of the contour surrounding the mask.
60  * The new visual content is determined by interpolating the color values of the contour pixels between corresponding pixels and each mask pixel lying on the line, between two matching pixels, located in the mask, will be adjusted/set.<br>
61  * Further, each mask pixel will be set to a non-mask pixel in the case the corresponding pixel in the frame has been adjusted/set.
62  * @param frame The frame for which the visual information (within the mask area) will be adjusted, must be valid
63  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
64  * @param width The width of the provided frame (and mask) in pixel, with range [1, infinity)
65  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
66  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
67  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
68  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
69  * @param boundingBox The bounding box
70  * @param mapping The pixel-wise mapping, matching to the contour, used to interpolate the visual content within the mask area
71  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
72  * @see contour2mapping8BitPerChannel().
73  */
74  template <unsigned int tChannels>
75  static void mappingInterpolation8BitPerChannel(uint8_t* frame, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions& denseContour, const PixelBoundingBox& boundingBox, const Indices32& mapping);
76 
77  private:
78 
79  /**
80  * Determines an initial mapping between all pixel of a contour based on simple geometrical and visual rules.
81  * @param frame The frame in which the contour is defined, must be valid
82  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
83  * @param outline An additional mask highlighting all pixels outlining the mask, so highlighting all pixels converted by the contour
84  * @param width The width of the provided frame (and masks) in pixel, with range [1, infinity)
85  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
86  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
87  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
88  * @param outlinePaddingElements The number of padding elements at the end of each outline row, in elements, with range [0, infinity)
89  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
90  * @param appearanceThreshold The maximal threshold for the appearance measure, with range [0, infinity)
91  * @return The resulting mapping for each pixel of the provided contour, for each (source) contour pixel the index of the corresponding (target) contour pixel will be provided, an index of -1 identifies pixels without corresponding pixel
92  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
93  */
94  template <unsigned int tChannels>
95  static Indices32 mappingInitialization8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions& denseContour, const unsigned int appearanceThreshold);
96 
97  /**
98  * Iteratively improves the mapping quality between contour pixels e.g., by propagating an initial mapping between all pixel of a contour based on simple geometrical and visual rules.
99  * @param frame The frame in which the contour is defined, must be valid
100  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
101  * @param outline An additional mask highlighting all pixels outlining the mask, so highlighting all pixels converted by the contour
102  * @param width The width of the provided frame (and masks) in pixel, with range [1, infinity)
103  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
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 outlinePaddingElements The number of padding elements at the end of each outline row, in elements, with range [0, infinity)
107  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
108  * @param mapping An already given initial mapping that will be improved, with ranges [0, width)x[0, height)
109  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
110  */
111  template <unsigned int tChannels>
112  static void improveMapping8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions& denseContour, Indices32& mapping);
113 
114  /**
115  * Determines the total cost of a pixel mapping during the forward propagation iteration including appearance and geometric costs.
116  * @param frame The frame in which the contour is defined, must be valid
117  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
118  * @param outline An additional mask highlighting all pixels outlining the mask, so highlighting all pixels converted by the contour
119  * @param width The width of the provided frame (and masks) in pixel, with range [1, infinity)
120  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
121  * @param frameStrideElements The number of elements between two frame rows, in elements, with range [width * tChannels, infinity)
122  * @param maskStrideElements The number of elements between two mask rows, in elements, with range [width * tChannels, infinity)
123  * @param outlineStrideElements The number of elements between two outline rows, in elements, with range [width * tChannels, infinity)
124  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
125  * @param mapping An already given initial mapping that will be improved, with ranges [0, width)x[0, height)
126  * @param sourceIndex The index of the source contour pixel, with range [0, denseContour.size())
127  * @param targetIndex The index of the target contour pixel, with range [0, denseContour.size())
128  * @param oneWay True, to measure the appearance cost regarding the previous neighbor; False, to measure the appearance cost regarding both (previous and next) neighbors
129  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
130  */
131  template <unsigned int tChannels>
132  static unsigned int totalForwardCost8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions& denseContour, const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay);
133 
134  /**
135  * Determines the total cost of a pixel mapping during the backward propagation iteration including appearance and geometric costs.
136  * @param frame The frame in which the contour is defined, must be valid
137  * @param mask The exclusive mask matching with the provided (surrounding) contour, with same frame dimension and pixel origin as the provided frame, must be valid
138  * @param outline An additional mask highlighting all pixels outlining the mask, so highlighting all pixels converted by the contour
139  * @param width The width of the provided frame (and masks) in pixel, with range [1, infinity)
140  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
141  * @param frameStrideElements The number of elements between two frame rows, in elements, with range [width * tChannels, infinity)
142  * @param maskStrideElements The number of elements between two mask rows, in elements, with range [width * tChannels, infinity)
143  * @param outlineStrideElements The number of elements between two outline rows, in elements, with range [width * tChannels, infinity)
144  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
145  * @param mapping An already given initial mapping that will be improved, with ranges [0, width)x[0, height)
146  * @param sourceIndex The index of the source (starting) contour pixel, with range [0, denseContour.size())
147  * @param targetIndex The index of the target (ending) contour pixel, with range [0, denseContour.size())
148  * @param oneWay True, to measure the appearance cost regarding the previous neighbor; False, to measure the appearance cost regarding both (previous and next) neighbors
149  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
150  */
151  template <unsigned int tChannels>
152  static unsigned int totalBackwardCost8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions& denseContour, const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay);
153 
154  /**
155  * Returns the appearance cost between two contour points using a [1 2 1] kernel.
156  * @param frame The frame in which the contour is defined, must be valid
157  * @param width The width of the provided frame (and masks) in pixel, with range [1, infinity)
158  * @param height The height of the provided frame (and mask) in pixel, with range [1, infinity)
159  * @param frameStrideElements The number of elements between two frame rows, in elements, with range [width * tChannels, infinity)
160  * @param denseContour The dense and distinct pixel contour defined in the domain of the frame, with ranges [0, width)x[0, height)
161  * @param sourceIndex The index of the source (starting) contour pixel, with range [0, denseContour.size())
162  * @param targetIndex The index of the target (ending) contour pixel, with range [0, denseContour.size())
163  * @return The appearance cost for the specified mapping, with range [0, infinity)
164  * @tparam tChannels The number of data channel the frame has, with range [1, infinity)
165  */
166  template <unsigned int tChannels>
167  static unsigned int directMappingCostAppearance8BitPerChannelKernel3(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const PixelPositions& denseContour, const unsigned int sourceIndex, const unsigned int targetIndex);
168 
169  /**
170  * Determines the geometric cost between two contour points while both neighbor pixels are included into the cost determination.
171  * @param mapping The mapping for which the cost will be determined, must be valid
172  * @param sourceIndex The index of the source (starting) contour pixel, with range [0, mapping.size())
173  * @param targetIndex The index of the target (ending) contour pixel, with range [0, mapping.size())
174  * @return The resulting geometry cost, with range [0, infinity)
175  */
176  static unsigned int neighborCostDistance(const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex);
177 
178  /**
179  * Determines the geometric cost between two contour points while the previous neighbor pixel is included into the cost determination.
180  * @param mapping The mapping for which the cost will be determined, must be valid
181  * @param sourceIndex The index of the source (starting) contour pixel, with range [0, mapping.size())
182  * @param targetIndex The index of the target (ending) contour pixel, with range [0, mapping.size())
183  * @return The resulting geometry cost, with range [0, infinity)
184  */
185  static unsigned int neighborCostDistanceMinus(const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex);
186 
187  /**
188  * Determines the geometric cost between two contour points while the next neighbor pixel is included into the cost determination.
189  * @param mapping The mapping for which the cost will be determined, must be valid
190  * @param sourceIndex The index of the source (starting) contour pixel, with range [0, mapping.size())
191  * @param targetIndex The index of the target (ending) contour pixel, with range [0, mapping.size())
192  * @return The resulting geometry cost, with range [0, infinity)
193  */
194  static unsigned int neighborCostDistancePlus(const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex);
195 
196  /**
197  * Determines the (signed) pixel distance along the contour between two location on the contour.
198  * @param highIndex The (higher) index of the first pixel location of the contour, with range [0, size)
199  * @param lowIndex The (lower) index of the second pixel location of the contour, with range [0, size)
200  * @param size The size of the contour in pixel, with range [1, infinity)
201  * @return The positive distance if higher >= lower; the negative distance otherwise, with range [-size/2, size/2]
202  */
203  static int distanceInContour(const unsigned int highIndex, const unsigned int lowIndex, const unsigned int size);
204 
205  /**
206  * Returns whether a specified line has at least one pixel outside a specified mask.
207  * Start and end pixel point of the given line are not considered and thus may lie outside the mask.
208  * @param mask The 8 bit mask frame with 0xFF defining a non-mask pixel, must be valid
209  * @param outline The 8 bit mask frame with 0x00 defining an outline pixel, with same frame dimension and frame orientation as the mask frame, must be valid
210  * @param width The width of the specified mask frame in pixel, with range [1, infinity)
211  * @param height The height of the specified mask frame in pixel, with range [1, infinity)
212  * @param maskStrideElements The number of elements between two mask rows, in elements, with range [width, infinity)
213  * @param outlineStrideElements The number of elements between two stride rows, in elements, with range [width, infinity)
214  * @param start The start point of the line to test, with range [-1, width]x[-1, height]
215  * @param stop The stop point of the line to test, with range [-1, width]x[-1, height]
216  * @return True, if so
217  */
218  static bool isLineOutsideMask(const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPosition& start, const PixelPosition& stop);
219 
220  /**
221  * Returns the square value of a given parameter.
222  * @param value The value to be squared
223  * @return Square value, with range [0, infinity)
224  */
225  static inline unsigned int sqr(const int value);
226 };
227 
228 template <unsigned int tChannels>
229 Indices32 ContourMapping::contour2mapping8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions& denseContour)
230 {
231  static_assert(tChannels != 0u, "Invalid channel number!");
232 
233  ocean_assert(frame != nullptr && mask != nullptr);
234  ocean_assert(width != 0u && height != 0u);
235 
236  Frame outlineFrame(FrameType(width, height, FrameType::FORMAT_Y8, FrameType::ORIGIN_UPPER_LEFT));
237  outlineFrame.setValue(0xFF);
238 
239  ocean_assert(PixelContour(denseContour).isDense());
240  ocean_assert(PixelContour(denseContour).isDistinct());
241 
242  for (const PixelPosition& densePixel : denseContour)
243  {
244  ocean_assert(densePixel.x() < width && densePixel.y() < height);
245 
246  outlineFrame.pixel<uint8_t>(densePixel.x(), densePixel.y())[0] = 0x00;
247  }
248 
249  Indices32 mapping(mappingInitialization8BitPerChannel<tChannels>(frame, mask, outlineFrame.constdata<uint8_t>(), width, height, framePaddingElements, maskPaddingElements, outlineFrame.paddingElements(), denseContour, tChannels * 35u * 35u));
250 
251  improveMapping8BitPerChannel<tChannels>(frame, mask, outlineFrame.constdata<uint8_t>(), width, height, framePaddingElements, maskPaddingElements, outlineFrame.paddingElements(), denseContour, mapping);
252 
253  return mapping;
254 }
255 
256 template <unsigned int tChannels>
257 void ContourMapping::mappingInterpolation8BitPerChannel(uint8_t* frame, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions& denseContour, const PixelBoundingBox& boundingBox, const Indices32& mapping)
258 {
259  static_assert(tChannels != 0u, "Invalid channel number!");
260 
261  ocean_assert(frame != nullptr && mask != nullptr);
262  ocean_assert(width != 0u && height != 0u);
263  ocean_assert(denseContour.size() == mapping.size());
264  ocean_assert(boundingBox && boundingBox.right() < width && boundingBox.bottom() < height);
265 
266  const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
267  const unsigned int maskStrideElements = width + maskPaddingElements;
268 
269  typedef typename DataType<uint8_t, tChannels>::Type PixelType;
270 
271  const unsigned int boundingBoxWidth = boundingBox.width();
272 
273  Frame holeFrame(FrameType(boundingBox.width(), boundingBox.height(), FrameType::genericPixelFormat<FrameType::DT_UNSIGNED_INTEGER_32, tChannels + 1u>(), FrameType::ORIGIN_UPPER_LEFT));
274  ocean_assert(holeFrame.isContinuous());
275 
276  holeFrame.setValue(0x00);
277 
278  uint32_t* const hole = holeFrame.data<uint32_t>();
279 
280  const unsigned int maxSqrLength = sqr(sqr(width) + sqr(height));
281 
282  for (unsigned int n = 0u; n < (unsigned int)mapping.size(); ++n)
283  {
284  const unsigned int sourceIndex = n;
285  const unsigned int targetIndex = mapping[sourceIndex];
286 
287  // check whether the contour pixel has no corresponding contour pixel
288  if (targetIndex >= mapping.size())
289  {
290  continue;
291  }
292 
293  ocean_assert(sourceIndex < denseContour.size());
294  ocean_assert(targetIndex < denseContour.size());
295 
296  const PixelPosition& source = denseContour[sourceIndex];
297  const PixelPosition& target = denseContour[targetIndex];
298 
299  ocean_assert(source.x() >= boundingBox.left());
300  ocean_assert(source.y() >= boundingBox.top());
301  ocean_assert(target.x() >= boundingBox.left());
302  ocean_assert(target.y() >= boundingBox.top());
303 
304  const int xSource = int(source.x() - boundingBox.left());
305  const int ySource = int(source.y() - boundingBox.top());
306 
307  const int xTarget = int(target.x() - boundingBox.left());
308  const int yTarget = int(target.y() - boundingBox.top());
309 
310  const PixelType sourcePixel = *(const PixelType*)(frame + source.y() * frameStrideElements + source.x() * tChannels);
311  const PixelType targetPixel = *(const PixelType*)(frame + target.y() * frameStrideElements + target.x() * tChannels);
312 
313  int x = xSource;
314  int y = ySource;
315 
316  CV::Bresenham bresenham(x, y, xTarget, yTarget);
317  unsigned int pixels = 1u;
318 
319  while (x != xTarget || y != yTarget)
320  {
321  ++pixels;
322  bresenham.findNext(x, y);
323  }
324 
325  x = xSource;
326  y = ySource;
327  bresenham = CV::Bresenham(x, y, xTarget, yTarget);
328  bresenham.findNext(x, y);
329  unsigned int t = 1u;
330 
331  const unsigned int sqrLength = sqr(source.sqrDistance(target));
332 
333  ocean_assert(maxSqrLength >= sqrLength);
334  const unsigned int weight = maxSqrLength / sqrLength;
335 
336  while (x != xTarget || y != yTarget)
337  {
338  ocean_assert(x >= 0 && x < int(width));
339  ocean_assert(y >= 0 && y < int(height));
340 
341  if (mask[(y + boundingBox.top()) * maskStrideElements + x + boundingBox.left()] == 0x00)
342  {
343  const unsigned int t1 = pixels - t;
344 
345  uint32_t* holeLocation = hole + 4u * (y * boundingBoxWidth + x);
346 
347  *holeLocation += weight;
348 
349  for (unsigned int i = 0u; i < tChannels; ++i)
350  {
351  const uint32_t value = uint32_t((((uint8_t*)&sourcePixel)[i] * t1 + ((uint8_t*)&targetPixel)[i] * t) / pixels);
352 
353  holeLocation[i + 1u] += value * weight;
354  }
355  }
356 
357  ++t;
358 
359  bresenham.findNext(x, y);
360  }
361  }
362 
363  for (unsigned int y = 0u; y < boundingBox.height(); ++y)
364  {
365  const uint32_t * holeLine = hole + 4u * (y * boundingBoxWidth);
366 
367  uint8_t* frameLine = frame + (y + boundingBox.top()) * frameStrideElements + boundingBox.left() * tChannels;
368  uint8_t* maskLine = mask + (y + boundingBox.top()) * maskStrideElements + boundingBox.left();
369 
370  for (unsigned int x = 0u; x < boundingBox.width(); ++x)
371  {
372  if (*holeLine)
373  {
374  for (unsigned int i = 0u; i < tChannels; ++i)
375  {
376  frameLine[i] = uint8_t(holeLine[i + 1u] / holeLine[0]);
377  }
378 
379  maskLine[0] = 0xFF;
380  }
381 
382  holeLine += 4;
383  frameLine += tChannels;
384  ++maskLine;
385  }
386  }
387 }
388 
389 template <unsigned int tChannels>
390 Indices32 ContourMapping::mappingInitialization8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions& denseContour, const unsigned int appearanceThreshold)
391 {
392  static_assert(tChannels != 0u, "Invalid channel number!");
393 
394  ocean_assert(frame != nullptr && mask != nullptr && outline != nullptr);
395  ocean_assert(width != 0u && height != 0u);
396 
397  const unsigned int contourSize = (unsigned int)(denseContour.size());
398  ocean_assert(contourSize > 3u);
399 
400  const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
401  const unsigned int maskStrideElements = width + maskPaddingElements;
402  const unsigned int outlineStrideElements = width + outlinePaddingElements;
403 
404  // initialization of an invalid mapping
405  Indices32 mapping(contourSize, (unsigned int)(-1));
406 
407  // find a first mapping by direct appearance cost only
408  for (unsigned int n = 0u; n < contourSize; ++n)
409  {
410  const PixelPosition& source = denseContour[n];
411 
412  unsigned int minCost = appearanceThreshold;
413  unsigned int minIndex = (unsigned int)(-1);
414 
415  for (unsigned int i = 0u; i < contourSize; ++i)
416  {
417  if (ringDistance(n, i, contourSize) > 5u || denseContour[n].sqrDistance(denseContour[i]) > 25u)
418  {
419  const PixelPosition& target = denseContour[i];
420 
421  if (!isLineOutsideMask(mask, outline, width, height, maskStrideElements, outlineStrideElements, source, target))
422  {
423  const unsigned int appearanceCost = directMappingCostAppearance8BitPerChannelKernel3<tChannels>(frame, width, height, frameStrideElements, denseContour, n, i);
424 
425  if (appearanceCost <= appearanceThreshold && appearanceCost < minCost)
426  {
427  minCost = appearanceCost;
428  minIndex = i;
429  }
430  }
431  }
432  }
433 
434  mapping[n] = minIndex;
435  }
436 
437  return mapping;
438 }
439 
440 template <unsigned int tChannels>
441 void ContourMapping::improveMapping8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions& denseContour, Indices32& mapping)
442 {
443  static_assert(tChannels != 0u, "Invalid channel number!");
444 
445  ocean_assert(frame != nullptr && mask != nullptr && outline != nullptr);
446  ocean_assert(width != 0u && height != 0u);
447  ocean_assert(denseContour.size() == mapping.size());
448 
449  const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
450  const unsigned int maskStrideElements = width + maskPaddingElements;
451  const unsigned int outlineStrideElements = width + outlinePaddingElements;
452 
453  RandomGenerator randomGenerator;
454 
455  const unsigned int contourSize = (unsigned int)denseContour.size();
456 
457  unsigned int iterations = 0u;
458  unsigned int changedMapping = contourSize;
459  bool firstIteration = true;
460 
461  while (changedMapping > 5u * contourSize / 100u && iterations < 50u)
462  {
463  changedMapping = 0u;
464  ++iterations;
465 
466  // forward optimization
467  for (unsigned int n = 0; n < contourSize + 5u; ++n) // 5 is the extra look
468  {
469  const unsigned int sourceIndex = (unsigned int)modulo(int(n), int(contourSize));
470  const unsigned int targetIndexStart = mapping[sourceIndex];
471 
472  // determine the current cost
473  unsigned int oldCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, mapping[sourceIndex], firstIteration);
474 
475  // check whether a mapping has to be removed due to changed cost conditions
476  if (oldCost == (unsigned int)(-1))
477  {
478  mapping[sourceIndex] = (unsigned int)(-1);
479  }
480 
481  // propagation step from minus-neighbor
482  {
483  const unsigned int sourceIndexMinus = (unsigned int)modulo(int(sourceIndex) - 1, int(contourSize));
484  const unsigned int targetIndexMinus = mapping[sourceIndexMinus];
485 
486  if (targetIndexMinus != (unsigned int)(-1))
487  {
488  // corresponding neighbor mapping
489  {
490  const unsigned int targetIndexMinusNeighbor = (unsigned int)modulo(int(targetIndexMinus) - 1, int(contourSize));
491  const unsigned int testCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, targetIndexMinusNeighbor, firstIteration);
492  if (testCost < oldCost)
493  {
494  oldCost = testCost;
495  mapping[sourceIndex] = targetIndexMinusNeighbor;
496  }
497  }
498 
499  // direct mapping
500  {
501  const unsigned int testCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, targetIndexMinus, firstIteration);
502  if (testCost < oldCost)
503  {
504  oldCost = testCost;
505  mapping[sourceIndex] = targetIndexMinus;
506  }
507  }
508  }
509  }
510 
511  // randomly find better mappings due to lowers costs
512  {
513  unsigned int minCost = oldCost;
514  unsigned int minTargetIndex = (unsigned int)(-1);
515 
516  for (unsigned int i = 0; i < 20u; ++i)
517  {
518  const unsigned int testTargetIndex = RandomI::random(randomGenerator, contourSize - 1u);
519  const unsigned int testCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, testTargetIndex, firstIteration);
520 
521  if (testCost < minCost)
522  {
523  minCost = testCost;
524  minTargetIndex = testTargetIndex;
525  }
526  }
527 
528  if (minTargetIndex != (unsigned int)(-1))
529  {
530  oldCost = minCost;
531  mapping[sourceIndex] = minTargetIndex;
532  }
533  }
534 
535  // (backwards) propagation step proposing the sourceIndex as mapping index for the targetIndex or its neighbor
536  {
537  const unsigned int targetIndex = mapping[sourceIndex];
538 
539  // check whether the source index is not the mapping index of the target index
540  if (targetIndex != (unsigned int)(-1) && sourceIndex != mapping[targetIndex])
541  {
542  const unsigned int oldTargetCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, targetIndex, mapping[targetIndex], firstIteration);
543  const unsigned int testTargetCost = totalForwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, targetIndex, sourceIndex, firstIteration);
544 
545  if (testTargetCost < oldTargetCost)
546  {
547  mapping[targetIndex] = sourceIndex;
548  }
549  }
550  }
551 
552  const unsigned int targetIndexEnd = mapping[sourceIndex];
553 
554  if (targetIndexStart != targetIndexEnd)
555  {
556  ++changedMapping;
557  }
558  }
559 
560 
561  // reverse optimization
562  for (int n = contourSize; n > -5; --n) // 5 is the extra look
563  {
564  const unsigned int sourceIndex = (unsigned int)modulo(int(n), int(contourSize));
565  const unsigned int targetIndexStart = mapping[sourceIndex];
566 
567  // determine the current cost
568  unsigned int oldCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, mapping[sourceIndex], firstIteration);
569 
570  // check whether a mapping has to be removed due to changed cost conditions
571  if (oldCost == (unsigned int)(-1))
572  {
573  mapping[sourceIndex] = (unsigned int)(-1);
574  }
575 
576  // propagation step from plus-neighbor
577  {
578  const unsigned int sourceIndexPlus = (unsigned int)modulo(int(sourceIndex) + 1, int(contourSize));
579  const unsigned int targetIndexPlus = mapping[sourceIndexPlus];
580 
581  if (targetIndexPlus != (unsigned int)(-1))
582  {
583  {
584  // corresponding neighbor mapping
585  const unsigned int targetIndexPlusNeighbor = (unsigned int)modulo(int(targetIndexPlus) + 1, int(contourSize));
586  const unsigned int testCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, targetIndexPlusNeighbor, firstIteration);
587  if (testCost < oldCost)
588  {
589  oldCost = testCost;
590  mapping[sourceIndex] = targetIndexPlusNeighbor;
591  }
592  }
593 
594  // direct mapping
595  {
596  const unsigned int testCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, targetIndexPlus, firstIteration);
597  if (testCost < oldCost)
598  {
599  oldCost = testCost;
600  mapping[sourceIndex] = targetIndexPlus;
601  }
602  }
603  }
604  }
605 
606  // randomly find better mappings due to lowers costs
607  {
608  unsigned int minCost = oldCost;
609  unsigned int minTargetIndex = (unsigned int)(-1);
610 
611  for (unsigned int i = 0; i < 20u; ++i)
612  {
613  const unsigned int testTargetIndex = RandomI::random(randomGenerator, contourSize - 1u);
614  const unsigned int testCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, sourceIndex, testTargetIndex, firstIteration);
615 
616  if (testCost < minCost)
617  {
618  minCost = testCost;
619  minTargetIndex = testTargetIndex;
620  }
621  }
622 
623  if (minTargetIndex != (unsigned int)(-1))
624  {
625  oldCost = minCost;
626  mapping[sourceIndex] = minTargetIndex;
627  }
628  }
629 
630  // (backwards) propagation step proposing the sourceIndex as mapping index for the targetIndex
631  {
632  const unsigned int targetIndex = mapping[sourceIndex];
633 
634  // check whether the source index is not the mapping index of the target index
635  if (targetIndex != (unsigned int)(-1) && sourceIndex != mapping[targetIndex])
636  {
637  const unsigned int oldTargetCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, targetIndex, mapping[targetIndex], firstIteration);
638  const unsigned int testTargetCost = totalBackwardCost8BitPerChannel<tChannels>(frame, mask, outline, width, height, frameStrideElements, maskStrideElements, outlineStrideElements, denseContour, mapping, targetIndex, sourceIndex, firstIteration);
639 
640  if (testTargetCost < oldTargetCost)
641  {
642  mapping[targetIndex] = sourceIndex;
643  }
644  }
645  }
646 
647  const unsigned int targetIndexEnd = mapping[sourceIndex];
648 
649  if (targetIndexStart != targetIndexEnd)
650  {
651  ++changedMapping;
652  }
653  }
654 
655  firstIteration = false;
656  }
657 }
658 
659 template <unsigned int tChannels>
660 unsigned int ContourMapping::totalForwardCost8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions& denseContour, const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay)
661 {
662  ocean_assert(frame != nullptr && mask != nullptr && outline != nullptr);
663  ocean_assert(width * tChannels < frameStrideElements);
664  ocean_assert(width < maskStrideElements);
665  ocean_assert(width < outlineStrideElements);
666 
667  ocean_assert(sourceIndex != (unsigned int)(-1));
668 
669  if (targetIndex == (unsigned int)(-1))
670  {
671  return (unsigned int)(-1);
672  }
673 
674  // test whether the offset inside the contour is large enough
675  if (ringDistance(sourceIndex, targetIndex, (unsigned int)denseContour.size()) <= 5u
676  && denseContour[sourceIndex].sqrDistance(denseContour[targetIndex]) <= 25u)
677  {
678  return (unsigned int)(-1);
679  }
680 
681  // test whether no line pixel is outside the mask
682  if (isLineOutsideMask(mask, outline, width, height, maskStrideElements, outlineStrideElements, denseContour[sourceIndex], denseContour[targetIndex]))
683  {
684  return (unsigned int)(-1);
685  }
686 
687  // the application of a use contour could improve the mapping quality
688  /*unsigned int usedCounter = 0;
689  for (Indices::const_iterator i = mapping.begin(); i != mapping.end(); ++i)
690  if (*i == targetIndex)
691  ++usedCounter;*/
692 
693  const unsigned int neighborCost = oneWay ? neighborCostDistanceMinus(mapping, sourceIndex, targetIndex) : neighborCostDistance(mapping, sourceIndex, targetIndex);
694 
695  const unsigned int appearanceThreshold = tChannels * 45u * 45u; // **TODO** threshold should be a function parameter
696 
697  const unsigned int costAppearance = directMappingCostAppearance8BitPerChannelKernel3<tChannels>(frame, width, height, frameStrideElements, denseContour, sourceIndex, targetIndex);
698  if (costAppearance > appearanceThreshold)
699  {
700  return (unsigned int)(-1);
701  }
702 
703  return costAppearance + 100u * sqr(neighborCost); // + 100u * sqr(usedCounter);
704 }
705 
706 template <unsigned int tChannels>
707 unsigned int ContourMapping::totalBackwardCost8BitPerChannel(const uint8_t* frame, const uint8_t* mask, const uint8_t* outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions& denseContour, const Indices32& mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay)
708 {
709  ocean_assert(sourceIndex != (unsigned int)(-1));
710 
711  if (targetIndex == (unsigned int)(-1))
712  {
713  return (unsigned int)(-1);
714  }
715 
716  // test whether the offset inside the contour is large enough
717  if (ringDistance(sourceIndex, targetIndex, (unsigned int)denseContour.size()) <= 5u
718  && denseContour[sourceIndex].sqrDistance(denseContour[targetIndex]) <= 25u)
719  {
720  return (unsigned int)(-1);
721  }
722 
723  // test whether no line pixel is outside the mask
724  if (isLineOutsideMask(mask, outline, width, height, maskStrideElements, outlineStrideElements, denseContour[sourceIndex], denseContour[targetIndex]))
725  {
726  return (unsigned int)(-1);
727  }
728 
729  // the application of a use contour could improve the mapping quality
730  /*unsigned int usedCounter = 0;
731  for (Indices::const_iterator i = mapping.begin(); i != mapping.end(); ++i)
732  if (*i == targetIndex)
733  ++usedCounter;*/
734 
735  const unsigned int neighborCost = oneWay ? neighborCostDistancePlus(mapping, sourceIndex, targetIndex) : neighborCostDistance(mapping, sourceIndex, targetIndex);
736 
737  const unsigned int appearanceThreshold = tChannels * 45u * 45u; // **TODO** threshold should be a function parameter
738 
739  const unsigned int costDirectAppearance = directMappingCostAppearance8BitPerChannelKernel3<tChannels>(frame, width, height, frameStrideElements, denseContour, sourceIndex, targetIndex);
740  if (costDirectAppearance > appearanceThreshold)
741  {
742  return (unsigned int)(-1);
743  }
744 
745  return costDirectAppearance + 100u * sqr(neighborCost); // + 100u * sqr(usedCounter);
746 }
747 
748 template <unsigned int tChannels>
749 unsigned int ContourMapping::directMappingCostAppearance8BitPerChannelKernel3(const uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const PixelPositions& denseContour, const unsigned int sourceIndex, const unsigned int targetIndex)
750 {
751  ocean_assert(frame != nullptr);
752  ocean_assert(width != 0u && height != 0u);
753  ocean_assert_and_suppress_unused(width * tChannels <= frameStrideElements, width);
754  ocean_assert(sourceIndex < denseContour.size());
755  ocean_assert(targetIndex < denseContour.size());
756 
757  const unsigned int sourceIndexMinus = (unsigned int)modulo(int(sourceIndex) - 1, int(denseContour.size()));
758  const unsigned int sourceIndexPlus = (unsigned int)modulo(int(sourceIndex) + 1, int(denseContour.size()));
759  ocean_assert(sourceIndexMinus < denseContour.size());
760  ocean_assert(sourceIndexPlus < denseContour.size());
761 
762  const unsigned int targetIndexMinus = (unsigned int)modulo(int(targetIndex) - 1, int(denseContour.size()));
763  const unsigned int targetIndexPlus = (unsigned int)modulo(int(targetIndex) + 1, int(denseContour.size()));
764  ocean_assert(targetIndexMinus < denseContour.size());
765  ocean_assert(targetIndexPlus < denseContour.size());
766 
767  const PixelPosition& sourceMinus = denseContour[sourceIndexMinus];
768  const PixelPosition& source = denseContour[sourceIndex];
769  const PixelPosition& sourcePlus = denseContour[sourceIndexPlus];
770  ocean_assert(sourceMinus.x() < width);
771  ocean_assert_and_suppress_unused(sourceMinus.y() < height, height);
772  ocean_assert(source.x() < width);
773  ocean_assert(source.y() < height);
774  ocean_assert(sourcePlus.x() < width);
775  ocean_assert(sourcePlus.y() < height);
776 
777  const PixelPosition& targetMinus = denseContour[targetIndexMinus];
778  const PixelPosition& target = denseContour[targetIndex];
779  const PixelPosition& targetPlus = denseContour[targetIndexPlus];
780  ocean_assert(targetMinus.x() < width);
781  ocean_assert(targetMinus.y() < height);
782  ocean_assert(target.x() < width);
783  ocean_assert(target.y() < height);
784  ocean_assert(targetPlus.x() < width);
785  ocean_assert(targetPlus.y() < height);
786 
787  const uint8_t* frameSourceMinus = frame + sourceMinus.y() * frameStrideElements + sourceMinus.x() * tChannels;
788  const uint8_t* frameTargetPlus = frame + targetPlus.y() * frameStrideElements + targetPlus.x() * tChannels;
789  const unsigned int ssdMinus = SumSquareDifferencesBase::buffer8BitPerChannelTemplate<tChannels>(frameSourceMinus, frameTargetPlus);
790 
791  const uint8_t* frameSource = frame + source.y() * frameStrideElements + source.x() * tChannels;
792  const uint8_t* frameTarget = frame + target.y() * frameStrideElements + target.x() * tChannels;
793  const unsigned int ssd = SumSquareDifferencesBase::buffer8BitPerChannelTemplate<tChannels>(frameSource, frameTarget);
794 
795  const uint8_t* frameSourcePlus = frame + sourcePlus.y() * frameStrideElements + sourcePlus.x() * tChannels;
796  const uint8_t* frameTargetMinus = frame + targetMinus.y() * frameStrideElements + targetMinus.x() * tChannels;
797  const unsigned int ssdPlus = SumSquareDifferencesBase::buffer8BitPerChannelTemplate<tChannels>(frameSourcePlus, frameTargetMinus);
798 
799  if (ssd > 100 && (ssdPlus > 2u * ssd || ssdMinus > 2u * ssd))
800  {
801  return (unsigned int)(-1);
802  }
803 
804  return (ssdMinus + 2u * ssd + ssdPlus) / 4u;
805 }
806 
807 inline unsigned int ContourMapping::sqr(const int value)
808 {
809  return value * value;
810 }
811 
812 }
813 
814 }
815 
816 }
817 
818 #endif // META_OCEAN_CV_SEGMENTATION_CONTOUR_MAPPING_H
This class implements bresenham line algorithms.
Definition: Bresenham.h:27
void findNext(int &x, int &y)
Applies one Bresenham step to find the next pixel.
T left() const
Returns the left (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:416
T right() const
Returns the right (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:430
T bottom() const
Returns the bottom (including) position of this bounding box.
Definition: PixelBoundingBox.h:444
unsigned int width() const
Returns the width (the number of horizontal including pixels) of this bounding box.
Definition: PixelBoundingBox.h:482
T top() const
Returns the top (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:423
unsigned int height() const
Returns the height (the number of vertical including pixels) of this bounding box.
Definition: PixelBoundingBox.h:489
T y() const
Returns the vertical coordinate position of this object.
Definition: PixelPosition.h:470
unsigned int sqrDistance(const PixelPositionT< T > &position) const
Returns the square difference between two pixel positions.
Definition: PixelPosition.h:489
T x() const
Returns the horizontal coordinate position of this object.
Definition: PixelPosition.h:458
This class determines mappings between pixels lying on a contour.
Definition: ContourMapping.h:37
static Indices32 mappingInitialization8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const uint8_t *outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions &denseContour, const unsigned int appearanceThreshold)
Determines an initial mapping between all pixel of a contour based on simple geometrical and visual r...
Definition: ContourMapping.h:390
static int distanceInContour(const unsigned int highIndex, const unsigned int lowIndex, const unsigned int size)
Determines the (signed) pixel distance along the contour between two location on the contour.
static unsigned int neighborCostDistance(const Indices32 &mapping, const unsigned int sourceIndex, const unsigned int targetIndex)
Determines the geometric cost between two contour points while both neighbor pixels are included into...
static unsigned int neighborCostDistanceMinus(const Indices32 &mapping, const unsigned int sourceIndex, const unsigned int targetIndex)
Determines the geometric cost between two contour points while the previous neighbor pixel is include...
static unsigned int directMappingCostAppearance8BitPerChannelKernel3(const uint8_t *frame, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const PixelPositions &denseContour, const unsigned int sourceIndex, const unsigned int targetIndex)
Returns the appearance cost between two contour points using a [1 2 1] kernel.
Definition: ContourMapping.h:749
static unsigned int totalForwardCost8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const uint8_t *outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions &denseContour, const Indices32 &mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay)
Determines the total cost of a pixel mapping during the forward propagation iteration including appea...
Definition: ContourMapping.h:660
static void improveMapping8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const uint8_t *outline, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const unsigned int outlinePaddingElements, const PixelPositions &denseContour, Indices32 &mapping)
Iteratively improves the mapping quality between contour pixels e.g., by propagating an initial mappi...
Definition: ContourMapping.h:441
static Indices32 contour2mapping8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions &denseContour)
Determines the mapping between pixels lying on a contour (defined within a frame) based on visual and...
Definition: ContourMapping.h:229
static bool isLineOutsideMask(const uint8_t *mask, const uint8_t *outline, const unsigned int width, const unsigned int height, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPosition &start, const PixelPosition &stop)
Returns whether a specified line has at least one pixel outside a specified mask.
static unsigned int neighborCostDistancePlus(const Indices32 &mapping, const unsigned int sourceIndex, const unsigned int targetIndex)
Determines the geometric cost between two contour points while the next neighbor pixel is included in...
static void mappingInterpolation8BitPerChannel(uint8_t *frame, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int maskPaddingElements, const PixelPositions &denseContour, const PixelBoundingBox &boundingBox, const Indices32 &mapping)
Replaces the visual content of a frame within a mask area by using the mapping information of the con...
Definition: ContourMapping.h:257
static unsigned int totalBackwardCost8BitPerChannel(const uint8_t *frame, const uint8_t *mask, const uint8_t *outline, const unsigned int width, const unsigned int height, const unsigned int frameStrideElements, const unsigned int maskStrideElements, const unsigned int outlineStrideElements, const PixelPositions &denseContour, const Indices32 &mapping, const unsigned int sourceIndex, const unsigned int targetIndex, const bool oneWay)
Determines the total cost of a pixel mapping during the backward propagation iteration including appe...
Definition: ContourMapping.h:707
static unsigned int sqr(const int value)
Returns the square value of a given parameter.
Definition: ContourMapping.h:807
Template class allowing to define an array of data types.
Definition: DataType.h:27
This class implements Ocean's image class.
Definition: Frame.h:1792
bool isContinuous() const
Returns whether all planes of this frame have continuous memory and thus do not contain any padding a...
Definition: Frame.h:4276
const T * constdata(const unsigned int planeIndex=0u) const
Returns a pointer to the read-only pixel data of a specific plane.
Definition: Frame.h:4168
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition: Frame.h:4159
T * pixel(const unsigned int x, const unsigned int y, const unsigned int planeIndex=0u)
Returns the pointer to the data of a specific pixel.
Definition: Frame.h:4209
bool setValue(const uint8_t value, const unsigned int planeIndex=0u, const bool skipPaddingData=true)
Sets the memory of the frame to a specified byte value (the memory of one plane).
unsigned int paddingElements(const unsigned int planeIndex=0u) const
Returns the optional number of padding elements at the end of each row for a specific plane.
Definition: Frame.h:4042
Definition of a frame type composed by the frame dimension, pixel format and pixel origin.
Definition: Frame.h:30
@ FORMAT_Y8
Pixel format for grayscale images with byte order Y and 8 bits per pixel.
Definition: Frame.h:594
@ ORIGIN_UPPER_LEFT
The first pixel lies in the upper left corner, the last pixel in the lower right corner.
Definition: Frame.h:1050
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
static unsigned int random(const unsigned int maxValue)
Returns one random integer value with specified maximum value.
T modulo(const T &value, const T &ring)
Returns the modulo value of a given parameter within a ring allowing positive and negative parameters...
Definition: base/Utilities.h:924
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition: Base.h:96
T ringDistance(const T &value0, const T &value1, const T &ring)
Returns the distance between two values inside defined ring.
Definition: base/Utilities.h:1018
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition: base/Utilities.h:1029
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition: PixelPosition.h:48
PixelContourT< unsigned int > PixelContour
Definition of the default PixelContour object with a data type allowing only positive coordinate valu...
Definition: PixelContour.h:29
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15