Ocean
Loading...
Searching...
No Matches
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"
22
23namespace Ocean
24{
25
26namespace CV
27{
28
29namespace Segmentation
30{
31
32/**
33 * This class determines mappings between pixels lying on a contour.
34 * @ingroup cvsegmentation
35 */
36class 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
228template <unsigned int tChannels>
229Indices32 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
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
256template <unsigned int tChannels>
257void 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
389template <unsigned int tChannels>
390Indices32 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
440template <unsigned int tChannels>
441void 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
659template <unsigned int tChannels>
660unsigned 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
706template <unsigned int tChannels>
707unsigned 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
748template <unsigned int tChannels>
749unsigned 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
807inline 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
This class implements Ocean's image class.
Definition Frame.h:1808
bool isContinuous() const
Returns whether all planes of this frame have continuous memory and thus do not contain any padding a...
Definition Frame.h:4356
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:4248
T * data(const unsigned int planeIndex=0u)
Returns a pointer to the pixel data of a specific plane.
Definition Frame.h:4239
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:4289
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:4122
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:36
The namespace covering the entire Ocean framework.
Definition Accessor.h:15
Default definition of a type with tBytes bytes.
Definition DataType.h:32