Ocean
MaskCreator.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_MASK_CREATOR_H
9 #define META_OCEAN_CV_SEGMENTATION_MASK_CREATOR_H
10 
13 
14 #include "ocean/base/Worker.h"
15 
18 
19 namespace Ocean
20 {
21 
22 namespace CV
23 {
24 
25 namespace Segmentation
26 {
27 
28 /**
29  * This class implements functions allowing to create or to modify masks.
30  * @ingroup cvsegmentation
31  */
32 class OCEAN_CV_SEGMENTATION_EXPORT MaskCreator
33 {
34  public:
35 
36  /**
37  * Creates a binary 8 bit (inclusive) mask for one given triangle, actually the triangle is painted into the frame with a specified color value.
38  * Inclusive means that the pixels inside the triangle as well as the pixels converted by the triangle (the corners, the lines between the corners) will be set to mask pixels.<br>
39  * Beware: The given triangle must entirely fit into the frame!
40  * @param mask The mask frame receiving the mask, must be valid
41  * @param width The width of the mask frame in pixel, with range [1, infinity)
42  * @param height The height of the mask frame in pixel, with range [1, infinity)
43  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
44  * @param triangle The triangle to create a mask from, must be valid but may be located outside the frame
45  * @param maskValue Mask value to be set, with range [0, 255]
46  * @tparam T The data type that is used to store the elements of a pixel coordinate, possible types are 'unsigned int' and 'int'
47  */
48  template <typename T>
49  static void triangle2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<T>& triangle, const uint8_t maskValue);
50 
51  /**
52  * Creates a binary 8 bit mask for several given triangles, actually the triangles will be painted into the frame with a specified color value.
53  * Inclusive means that the pixels inside the triangles as well as the pixels converted by the triangles (the corners, the lines between the corners) will be set to mask pixels.<br>
54  * Beware: All triangles must entirely fit into the frame!
55  * @param mask The mask frame receiving the mask, must be valid
56  * @param width The width of the mask frame in pixel, with range [1, infinity)
57  * @param height The height of the mask frame in pixel, with range [1, infinity)
58  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
59  * @param triangles The triangles to create a mask from all fitting entirely into the mask frame
60  * @param size The number of provided triangles, with rang [1, infinity)
61  * @param maskValue Mask value to be set, with range [0, 255]
62  * @param worker Optional worker object to distribute the computation
63  */
64  template <typename T>
65  static inline void triangles2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<T>* triangles, const size_t size, const uint8_t maskValue, Worker* worker = nullptr);
66 
67  /**
68  * Smooths a given 8 bit mask frame by adding additional outline-4 mask pixels with incrementing values within several iterations.
69  * @param mask The mask frame to be smoothed, must be valid
70  * @param width The width of the mask frame in pixel, with range [1, infinity)
71  * @param height The height of the mask frame in pixel, with range [1, infinity)
72  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
73  * @param iterations Number of smoothing iterations (equivalent to the number of new border pixels around the original mask), with range [1, 255]
74  * @param incrementValue Mask value offset to be added for each iteration, with range [1, 255 / iterations]
75  */
76  static void smoothMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int iterations, const unsigned int incrementValue);
77 
78  /**
79  * Creates a binary 8 bit (inclusive) mask for a given sparse or dense contour.
80  * The contour is triangulated and than converted to a mask.<br>
81  * Due to performance reasons and due to irregular coordinates a sparse contours is recommended.<br>
82  * In any case, the provided pixel contour should be simplified.
83  * @param mask The mask frame receiving the mask, must be valid
84  * @param width The width of the mask frame in pixel, with range [1, infinity)
85  * @param height The height of the mask frame in pixel, with range [1, infinity)
86  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
87  * @param simplifiedContour The (simplified) contour from which the mask will be created, must entirely fit into the frame, e.g., pixelContour.boundingBox().right() < width, pixelContour.boundingBox().bottom() < height
88  * @param maskValue Mask value to be assigned, with range [0, 255]
89  * @param worker Optional worker object to distribute the computation
90  * @param triangulationForced Optional resulting statement whether the contour needed to be forced to a triangulation (so that the resulting mask may be faulty); True, if so
91  * @return True, if succeeded
92  * @see denseContour2inclusiveMaskHotizontallyConvex().
93  */
94  static bool contour2inclusiveMaskByTriangulation(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& simplifiedContour, const unsigned int maskValue, Worker* worker = nullptr, bool* triangulationForced = nullptr);
95 
96  /**
97  * Creates a binary 8 bit horizontally-convex (inclusive) mask from a given dense contour.
98  * As the mask will be inclusive all contour pixels (and the pixels inside the contour) will become mask pixels.<br>
99  * This function does not triangulate the given contour so that the function is faster than contour2inclusiveMaskByTriangulation().<br>
100  * Instead, this function determines the first and last mask pixel in every row of the frame and sets all pixel within the ranges to specified mask value.<br>
101  * However, as for each row only one start and end point is determined (the extreme values), vertical holes will be filled with mask pixel.
102  * @param mask 8 bit frame receiving the mask, must be valid
103  * @param width The width of the frame in pixel, with range [1, infinity)
104  * @param height The height of the frame in pixel, with range [1, infinity)
105  * @param densePixelPositions Dense contour pixels, successive pixels must be in the direct 8-neighborhood, each pixel position with range [0, infinity)x[0, infinity)
106  * @param maskValue Mask value to be assigned, with range [0, 255]
107  * @see denseContour2inclusiveMask(), contour2inclusiveMaskByTriangulation().
108  */
109  static void denseContour2inclusiveMaskHotizontallyConvex(uint8_t* mask, const unsigned int width, const unsigned int height, const PixelPositions& densePixelPositions, const uint8_t maskValue);
110 
111  /**
112  * Creates a binary 8 bit (inclusive) mask from a given dense and distinct contour.
113  * As the mask will be inclusive all contour pixels (and the pixels inside the contour) will become mask pixels.<br>
114  * This function does not triangulate the given contour so that the function is faster than contour2inclusiveMaskByTriangulation().<br>
115  * Instead, this function determines horizontal sections of joined mask pixels in every row of the frame and sets all pixel within the ranges to specified mask value.<br>
116  * This function creates concave (and convex) masks and therefore is more precisely as denseContour2inclusiveMaskHotizontallyConvex(), but therefore slightly slower.
117  * @param mask 8 bit frame receiving the mask, must be valid
118  * @param width The width of the frame in pixel, with range [1, infinity)
119  * @param height The height of the frame in pixel, with range [1, infinity)
120  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
121  * @param denseContour Dense and distinct contour for which the mask will be created, each pixel position with range [0, width)x[0, height)
122  * @param maskValue Mask value to be assigned, with range [0, 255]
123  * @see denseContour2exclusiveMask(), contour2inclusiveMaskByTriangulation().
124  */
125  static inline void denseContour2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t maskValue);
126 
127  /**
128  * Creates a binary 8 bit (exclusive) mask from a given dense and distinct contour.
129  * As the mask will be exclusive, pixels inside the contour will become mask pixels but not the pixels of the contour.<br>
130  * This function does not triangulate the given contour so that the function is faster than contour2inclusiveMaskByTriangulation().<br>
131  * Instead, this function determines horizontal sections of joined mask pixels in every row of the frame and sets all pixel within the ranges to specified mask value.<br>
132  * This function creates concave (and convex) masks and therefore is more precisely as denseContour2inclusiveMaskHotizontallyConvex(), but therefore slightly slower.
133  * @param mask 8 bit frame receiving the mask, must be valid
134  * @param width The width of the frame in pixel, with range [1, infinity)
135  * @param height The height of the frame in pixel, with range [1, infinity)
136  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
137  * @param denseContour Dense and distinct contour for which the mask will be created, each pixel position with range [0, width)x[0, height)
138  * @param maskValue Mask value to be assigned, with range [0, 255]
139  * @see denseContour2inclusiveMask(), contour2inclusiveMaskByTriangulation().
140  */
141  static inline void denseContour2exclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t maskValue);
142 
143  /**
144  * Creates a binary 8 bit (inclusive) mask from a given dense and distinct contour.
145  * As the mask will be inclusive all contour pixels (and the pixels inside the contour) will be XORed with a specified reference values.<br>
146  * Instead, this function determines horizontal sections of joined mask pixels in every row of the frame and handles all pixel within the ranges with XOR.
147  * @param mask 8 bit frame receiving the mask, must be valid
148  * @param width The width of the frame in pixel, with range [1, infinity)
149  * @param height The height of the frame in pixel, with range [1, infinity)
150  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
151  * @param denseContour Dense and distinct contour for which the mask will be created, each pixel position with range [0, width)x[0, height)
152  * @param xorReference The reference value for the XOR operator, with range [0, 255]
153  * @see denseContour2exclusiveMaskXOR(), denseContour2exclusiveMask(), contour2inclusiveMaskByTriangulation().
154  */
155  static inline void denseContour2inclusiveMaskXOR(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t xorReference = 0xFF);
156 
157  /**
158  * Creates a binary 8 bit (exclusive) mask from a given dense and distinct contour.
159  * As the mask will be exclusive, pixels inside the contour will be XORed but not the pixels of the contour.<br>
160  * Instead, this function determines horizontal sections of joined mask pixels in every row of the frame and handles all pixel within the ranges with XOR.
161  * @param mask 8 bit frame receiving the mask, must be valid
162  * @param width The width of the frame in pixel, with range [1, infinity)
163  * @param height The height of the frame in pixel, with range [1, infinity)
164  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
165  * @param denseContour Dense and distinct contour for which the mask will be created, each pixel position with range [0, width)x[0, height)
166  * @param xorReference The reference value for the XOR operator, with range [0, 255]
167  * @see denseContour2inclusiveMaskXOR(), denseContour2exclusiveMask(), contour2inclusiveMaskByTriangulation().
168  */
169  static inline void denseContour2exclusiveMaskXOR(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t xorReference = 0xFF);
170 
171  /**
172  * Creates an 8 bit mask from a given 1 channel 32 bit separation frame.
173  * The separation frame holds mask blocks with individual ids identifying individual blocks (the ids allow to separate the blocks).<br>
174  * This function actually does the following:
175  * <pre>
176  * if separation[x, y] == id
177  * {
178  * mask[x, y] = maskValue
179  * }
180  * </pre>
181  * @param separation The separation frame composed of individual blocks with individual ids, must be valid
182  * @param width The width of the separation frame (and the mask frame) in pixel, with range [1, infinity)
183  * @param height The height of the separation frame (and the mask frame) in pixel, with range [1, infinity)
184  * @param separationPaddingElements The number of padding elements at the end of each separation row, in elements, with range [0, infinity)
185  * @param id The id for which the corresponding mask pixels will be changed/set to a specified mask value
186  * @param mask The mask frame in which the specific pixels will be set to the specified mask value, with same dimension and pixel origin as the separation frame, must be valid
187  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
188  * @param maskValue The value to be set to each mask pixel for which the corresponding separation pixel is equal to the specified id
189  */
190  static void separation2mask(const uint32_t* separation, const unsigned int width, const unsigned int height, const unsigned int separationPaddingElements, const uint32_t id, uint8_t* mask, const unsigned int maskPaddingElements, const uint8_t maskValue = 0x00);
191 
192  /**
193  * Creates an 8 bit mask from a given 1 channel 32 bit separation frame.
194  * The separation frame holds mask blocks with individual ids identifying individual blocks (the ids allow to separate the blocks).<br>
195  * This function takes a lookup table with separation ids defining whether the corresponding mask block receives a new pixel value or not.<br>
196  * This function actually does the following:
197  * <pre>
198  * if ids[ separation[x, y] ] == true
199  * {
200  * mask[x, y] = maskValue
201  * }
202  * </pre>
203  * @param separation The separation frame composed of individual blocks with individual ids, must be valid
204  * @param width The width of the separation frame (and the mask frame) in pixel, with range [1, infinity)
205  * @param height The height of the separation frame (and the mask frame) in pixel, with range [1, infinity)
206  * @param separationPaddingElements The number of padding elements at the end of each separation row, in elements, with range [0, infinity)
207  * @param ids Id lookup table defining whether the corresponding pixels receive the specified mask value, a lookup value not equal to 0x00 sets the mask pixel
208  * @param numberIds Size of the lookup table, must have one entry for each id from the separation frame, with range [1, infinity)
209  * @param maskValue The value to be set to each mask pixel for which the corresponding separation pixel is equal to the specified id
210  * @param mask The mask frame in which the specific pixels will be set to the specified mask value, with same dimension and pixel origin as the separation frame, must be valid
211  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
212  */
213  static void separations2mask(const uint32_t* separation, const unsigned int width, const unsigned int height, const unsigned int separationPaddingElements, const uint8_t* ids, const size_t numberIds, const uint8_t maskValue, uint8_t* mask, const unsigned int maskPaddingElements);
214 
215  /**
216  * Joins two 8 bit masks with respect to a specific mask value.
217  * This function actually does the following:
218  * <pre>
219  * if mask[x, y] == maskValue || target[x, y] == maskValue
220  * {
221  * target[x, y] = maskValue
222  * }
223  * </pre>
224  * @param mask The first mask which will be joined with (added to) the second (target) mask, must be valid
225  * @param target The target mask which is the second mask and also the final joined mask with same dimension and pixel origin as the first mask, must be valid
226  * @param width The width of both masks in pixel, with range [1, infinity)
227  * @param height The height of both masks in pixel, with range [1, infinity)
228  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
229  * @param targetPaddingElements the number of padding elements at the end of each target row, in elements, with range [0, infinity)
230  * @param maskValue The mask pixel value, a pixel in the joined mask is set to this value if the value is either in the first or in the second mask
231  * @param worker Optional worker object to distribute the computation
232  */
233  static inline void joinMasks(const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int targetPaddingElements, const uint8_t maskValue = 0x00, Worker* worker = nullptr);
234 
235  private:
236 
237  /**
238  * Determines the group of horizontal pixel offset locations for a given dense and distinct contour so that an (inclusive) mask can be created from the offsets afterwards.
239  * @param denseDistinctContour The dense and distinct contour for which the groups of horizontal pixel offsets will be determined
240  * @param offsetGroups The resulting groups of horizontal pixel offsets, the size of the vector must be pre-initialized with the height of the resulting mask frame
241  */
242  static void denseContour2inclusiveMaskOffsets(const PixelContour& denseDistinctContour, IndexGroups32& offsetGroups);
243 
244  /**
245  * Determines the group of horizontal pixel offset locations for a given dense and distinct contour so that an (exclusive) mask can be created from the offsets afterwards.
246  * @param denseDistinctContour The dense and distinct contour for which the groups of horizontal pixel offsets will be determined
247  * @param offsetGroups The resulting groups of horizontal pixel offsets, the size of the vector must be pre-initialized with the height of the resulting mask frame
248  */
249  static void denseContour2exclusiveMaskOffsets(const PixelContour& denseDistinctContour, IndexGroups32& offsetGroups);
250 
251  /**
252  * Creates an (inclusive) 8 bit mask for a given group of horizontal pixel offset locations.
253  * For each mask row pixel offset locations define the horizontal start and end points of joined mask ranges while a row may have several start and end points following on each other.<br>
254  * The number of start end points for each row must be even: e.g., [start0, end0] [start1, end1] and so on.<br>
255  * However, start and end points do not need to be sorted according to their horizontal location, this is done internally.
256  * @param offsetGroups The groups of horizontal offset values, with offsets.size() <= height, the individual offsets will be sorted according their horizontal location during the execution
257  * @param mask The mask frame receiving the mask, must be valid
258  * @param width The width of the mask frame in pixel, with range [1, infinity)
259  * @param height The height of the mask frame in pixel, with range [1, infinity)
260  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
261  * @param maskValue The mask value to be set for each pixel within start and end ranges, with range [0, 255]
262  */
263  static void inclusiveMaskOffsets2inclusiveMask(IndexGroups32& offsetGroups, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t maskValue);
264 
265  /**
266  * Creates an (exclusive) 8 bit mask for a given group of horizontal pixel offset locations.
267  * For each mask row pixel offset locations define the horizontal start and end points of joined mask ranges while a row may have several start and end points following on each other.<br>
268  * The number of start end points for each row must be even: e.g., [start0, end0] [start1, end1] and so on.<br>
269  * However, start and end points do not need to be sorted according to their horizontal location, this is done internally.
270  * @param offsetGroups The groups of horizontal offset values, with offsets.size() <= height, the individual offsets will be sorted according their horizontal location during the execution
271  * @param mask The mask frame receiving the mask, must be valid
272  * @param width The width of the mask frame in pixel, with range [1, infinity)
273  * @param height The height of the mask frame in pixel, with range [1, infinity)
274  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
275  * @param maskValue The mask value to be set for each pixel within start and end ranges, with range [0, 255]
276  */
277  static void exclusiveMaskOffsets2exclusiveMask(IndexGroups32& offsetGroups, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t maskValue);
278 
279  /**
280  * Creates an (inclusive) 8 bit mask for a given group of horizontal pixel offset locations.
281  * For each mask row pixel offset locations define the horizontal start and end points of joined mask ranges while a row may have several start and end points following on each other.<br>
282  * The number of start end points for each row must be even: e.g., [start0, end0] [start1, end1] and so on.<br>
283  * However, start and end points do not need to be sorted according to their horizontal location, this is done internally.
284  * @param offsetGroups The groups of horizontal offset values, with offsets.size() <= height, the individual offsets will be sorted according their horizontal location during the execution
285  * @param mask The mask frame receiving the mask, must be valid
286  * @param width The width of the mask frame in pixel, with range [1, infinity)
287  * @param height The height of the mask frame in pixel, with range [1, infinity)
288  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
289  * @param xorReference The reference value for the XOR operator to be used for each pixel within start and end ranges, with range [0, 255]
290  */
291  static void inclusiveMaskOffsets2inclusiveMaskXOR(IndexGroups32& offsetGroups, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t xorReference);
292 
293  /**
294  * Creates an (exclusive) 8 bit mask for a given group of horizontal pixel offset locations.
295  * For each mask row pixel offset locations define the horizontal start and end points of joined mask ranges while a row may have several start and end points following on each other.<br>
296  * The number of start end points for each row must be even: e.g., [start0, end0] [start1, end1] and so on.<br>
297  * However, start and end points do not need to be sorted according to their horizontal location, this is done internally.
298  * @param offsetGroups The groups of horizontal offset values, with offsets.size() <= height, the individual offsets will be sorted according their horizontal location during the execution
299  * @param mask The mask frame receiving the mask, must be valid
300  * @param width The width of the mask frame in pixel, with range [1, infinity)
301  * @param height The height of the mask frame in pixel, with range [1, infinity)
302  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
303  * @param xorReference The reference value for the XOR operator to be used for each pixel within start and end ranges, with range [0, 255]
304  */
305  static void exclusiveMaskOffsets2exclusiveMaskXOR(IndexGroups32& offsetGroups, uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t xorReference);
306 
307  /**
308  * Creates a binary 8 bit mask for a subset of several given triangles, actually the triangles will be painted into the frame with a specified color value.
309  * Beware: All triangles must entirely fit into the frame!
310  * @param mask The mask frame receiving the mask, must be valid
311  * @param width The width of the mask frame in pixel, with range (0, infinity)
312  * @param height The height of the mask frame in pixel, with range (0, infinity)
313  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
314  * @param triangles The triangles to create a mask from all fitting entirely into the mask frame
315  * @param maskValue Mask value to be set, with range [0, 255]
316  * @param firstTriangle First triangle to be handled, with range [0, 'size')
317  * @param numberTriangles Number of triangles to be handled, with range [1, 'size')
318  * @tparam T The data type that is used to store the elements of a pixel coordinate, possible types are 'unsigned int' and 'int'
319  */
320  template <typename T>
321  static inline void triangles2inclusiveMaskSubset(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<T>* triangles, const uint8_t maskValue, const unsigned int firstTriangle, const unsigned int numberTriangles);
322 
323  /**
324  * Joins two 8 bit masks with respect to a specific mask value.
325  * @param mask The first mask which will be joined with (added to) the second (target) mask, must be valid
326  * @param target The target mask which is the second mask and also the final joined mask with same dimension and pixel origin as the first mask, must be valid
327  * @param width The width of both masks in pixel, with range [1, infinity)
328  * @param height The height of both masks in pixel, with range [1, infinity)
329  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
330  * @param targetPaddingElements the number of padding elements at the end of each target row, in elements, with range [0, infinity)
331  * @param maskValue The mask pixel value, a pixel in the joined mask is set to this value if the value is either in the first or in the second mask
332  * @param firstRow The first row to be handled, with range [0, height)
333  * @param numberRows The number of rows to be handled, with range [1, height]
334  * @see joinMasks().
335  */
336  static void joinMasksSubset(const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int targetPaddingElements, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows);
337 };
338 
339 template <>
340 inline void MaskCreator::triangle2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<unsigned int>& triangle, const uint8_t maskValue)
341 {
342  ocean_assert(mask != nullptr && width != 0u && height != 0u);
343 
344  if (triangle.left() >= width || triangle.top() >= height)
345  {
346  return;
347  }
348 
349  const unsigned int maskStrideElements = width + maskPaddingElements;
350 
351  const unsigned int yMin = triangle.top();
352  const unsigned int yMax = min(triangle.bottom(), height - 1u);
353 
354  const Advanced::PixelLineT<unsigned int> l01(triangle.point0().x(), triangle.point0().y(), triangle.point1().x(), triangle.point1().y());
355  const Advanced::PixelLineT<unsigned int> l02(triangle.point0().x(), triangle.point0().y(), triangle.point2().x(), triangle.point2().y());
356  const Advanced::PixelLineT<unsigned int> l12(triangle.point1().x(), triangle.point1().y(), triangle.point2().x(), triangle.point2().y());
357 
358  unsigned int x01, x02, x12;
359 
360  for (unsigned int y = yMin; y <= yMax; ++y)
361  {
362  unsigned int xMin = 0xFFFFFFFF;
363  unsigned int xMax = 0;
364 
365  if (l01.horizontalIntersection(y, x01))
366  {
367  xMin = min(xMin, x01);
368  xMax = max(xMax, x01);
369 
370  if (l01.isHorizontal())
371  {
372  xMin = min(xMin, min(l01.p0().x(), l01.p1().x()));
373  xMax = max(xMax, max(l01.p0().x(), l01.p1().x()));
374  }
375  }
376 
377  if (l02.horizontalIntersection(y, x02))
378  {
379  xMin = min(xMin, x02);
380  xMax = max(xMax, x02);
381 
382  if (l02.isHorizontal())
383  {
384  xMin = min(xMin, min(l02.p0().x(), l02.p1().x()));
385  xMax = max(xMax, max(l02.p0().x(), l02.p1().x()));
386  }
387  }
388 
389  if (l12.horizontalIntersection(y, x12))
390  {
391  xMin = min(xMin, x12);
392  xMax = max(xMax, x12);
393 
394  if (l12.isHorizontal())
395  {
396  xMin = min(xMin, min(l12.p0().x(), l12.p1().x()));
397  xMax = max(xMax, max(l12.p0().x(), l12.p1().x()));
398  }
399  }
400 
401  if (xMin <= xMax)
402  {
403  memset(mask + y * maskStrideElements + xMin, maskValue, xMax - xMin + 1u);
404  }
405  }
406 }
407 
408 template <>
409 inline void MaskCreator::triangle2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<int>& triangle, const uint8_t maskValue)
410 {
411  ocean_assert(mask && width != 0u && height != 0u);
412 
413  if (triangle.left() >= int(width) || triangle.right() < 0 || triangle.top() >= int(height) || triangle.bottom() < 0)
414  {
415  return;
416  }
417 
418  const unsigned int maskStrideElements = width + maskPaddingElements;
419 
420  const int yMin = max(0, triangle.top());
421  const int yMax = min(triangle.bottom(), int(height - 1u));
422 
423  ocean_assert(yMin >= 0 && yMax < int(height) && yMin < yMax);
424 
425  const Advanced::PixelLineT<int> l01(triangle.point0().x(), triangle.point0().y(), triangle.point1().x(), triangle.point1().y());
426  const Advanced::PixelLineT<int> l02(triangle.point0().x(), triangle.point0().y(), triangle.point2().x(), triangle.point2().y());
427  const Advanced::PixelLineT<int> l12(triangle.point1().x(), triangle.point1().y(), triangle.point2().x(), triangle.point2().y());
428 
429  int x01, x02, x12;
430 
431  for (int y = yMin; y <= yMax; ++y)
432  {
433  int xMin = NumericT<int>::maxValue();
434  int xMax = NumericT<int>::minValue();
435 
436  if (l01.horizontalIntersection(y, x01))
437  {
438  xMin = min(xMin, x01);
439  xMax = max(xMax, x01);
440 
441  if (l01.isHorizontal())
442  {
443  xMin = min(xMin, min(l01.p0().x(), l01.p1().x()));
444  xMax = max(xMax, max(l01.p0().x(), l01.p1().x()));
445  }
446  }
447 
448  if (l02.horizontalIntersection(y, x02))
449  {
450  xMin = min(xMin, x02);
451  xMax = max(xMax, x02);
452 
453  if (l02.isHorizontal())
454  {
455  xMin = min(xMin, min(l02.p0().x(), l02.p1().x()));
456  xMax = max(xMax, max(l02.p0().x(), l02.p1().x()));
457  }
458  }
459 
460  if (l12.horizontalIntersection(y, x12))
461  {
462  xMin = min(xMin, x12);
463  xMax = max(xMax, x12);
464 
465  if (l12.isHorizontal())
466  {
467  xMin = min(xMin, min(l12.p0().x(), l12.p1().x()));
468  xMax = max(xMax, max(l12.p0().x(), l12.p1().x()));
469  }
470  }
471 
472  if (xMin < 0)
473  {
474  xMin = 0;
475  }
476 
477  if (xMax >= int(width))
478  {
479  xMax = int(width) - 1;
480  }
481 
482  if (xMin <= xMax)
483  {
484  memset(mask + y * maskStrideElements + xMin, maskValue, xMax - xMin + 1u);
485  }
486  }
487 }
488 
489 template <typename T>
490 inline void MaskCreator::triangles2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<T>* triangles, const size_t size, const uint8_t maskValue, Worker* worker)
491 {
492  ocean_assert(mask != nullptr && width != 0u && height != 0u);
493  ocean_assert(triangles != nullptr && size != 0);
494 
495  if (worker)
496  {
497  worker->executeFunction(Worker::Function::createStatic(&MaskCreator::triangles2inclusiveMaskSubset, mask, width, height, maskPaddingElements, triangles, maskValue, 0u, 0u), 0u, (unsigned int)(size));
498  }
499  else
500  {
501  triangles2inclusiveMaskSubset(mask, width, height, maskPaddingElements, triangles, maskValue, 0u, (unsigned int)(size));
502  }
503 }
504 
505 inline void MaskCreator::denseContour2inclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t maskValue)
506 {
507  ocean_assert(mask && width != 0u && height != 0u);
508 
509  IndexGroups32 offsetGroups(height);
510  denseContour2inclusiveMaskOffsets(denseContour, offsetGroups);
511  inclusiveMaskOffsets2inclusiveMask(offsetGroups, mask, width, height, maskPaddingElements, maskValue);
512 }
513 
514 inline void MaskCreator::denseContour2inclusiveMaskXOR(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t xorReference)
515 {
516  ocean_assert(mask && width != 0u && height != 0u);
517 
518  IndexGroups32 offsetGroups(height);
519  denseContour2inclusiveMaskOffsets(denseContour, offsetGroups);
520  inclusiveMaskOffsets2inclusiveMaskXOR(offsetGroups, mask, width, height, maskPaddingElements, xorReference);
521 }
522 
523 inline void MaskCreator::denseContour2exclusiveMask(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t maskValue)
524 {
525  ocean_assert(mask && width != 0u && height != 0u);
526 
527  IndexGroups32 offsetGroups(height);
528  denseContour2exclusiveMaskOffsets(denseContour, offsetGroups);
529  exclusiveMaskOffsets2exclusiveMask(offsetGroups, mask, width, height, maskPaddingElements, maskValue);
530 }
531 
532 inline void MaskCreator::denseContour2exclusiveMaskXOR(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour& denseContour, const uint8_t xorReference)
533 {
534  ocean_assert(mask && width != 0u && height != 0u);
535 
536  IndexGroups32 offsetGroups(height);
537  denseContour2exclusiveMaskOffsets(denseContour, offsetGroups);
538  exclusiveMaskOffsets2exclusiveMaskXOR(offsetGroups, mask, width, height, maskPaddingElements, xorReference);
539 }
540 
541 inline void MaskCreator::joinMasks(const uint8_t* mask, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int targetPaddingElements, const uint8_t maskValue, Worker* worker)
542 {
543  ocean_assert(mask != nullptr && target != nullptr);
544  ocean_assert(width != 0u && height != 0u);
545 
546  if (worker)
547  {
548  worker->executeFunction(Worker::Function::createStatic(&MaskCreator::joinMasksSubset, mask, target, width, height, maskPaddingElements, targetPaddingElements, maskValue, 0u, 0u), 0u, height, 7u, 8u, 20u);
549  }
550  else
551  {
552  joinMasksSubset(mask, target, width, height, maskPaddingElements, targetPaddingElements, maskValue, 0u, height);
553  }
554 }
555 
556 template <typename T>
557 inline void MaskCreator::triangles2inclusiveMaskSubset(uint8_t* mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT<T>* triangles, const uint8_t maskValue, const unsigned int firstTriangle, const unsigned int numberTriangles)
558 {
559  ocean_assert(mask && triangles);
560 
561  for (unsigned int n = firstTriangle; n < firstTriangle + numberTriangles; ++n)
562  {
563  triangle2inclusiveMask(mask, width, height, maskPaddingElements, triangles[n], maskValue);
564  }
565 }
566 
567 }
568 
569 }
570 
571 }
572 
573 #endif // META_OCEAN_CV_SEGMENTATION_MASK_CREATOR_H
This class implements a 2D line with pixel precision.
Definition: PixelLine.h:65
bool isHorizontal() const
Returns whether this line is horizontal.
Definition: PixelLine.h:215
const PixelPositionT< T > & p0() const
Returns the first end point of this line.
Definition: PixelLine.h:203
const PixelPositionT< T > & p1() const
Returns the second end point of this line.
Definition: PixelLine.h:209
bool horizontalIntersection(const T y, T &x) const
Calculates the intersection between this line and a horizontal scan line.
Definition: PixelLine.h:236
This class implements a 2D triangle with pixel precision.
Definition: PixelTriangle.h:70
T right() const
Returns the most right (including) position of this triangle.
Definition: PixelTriangle.h:259
const PixelPositionT< T > & point1() const
Returns the second corner point of this triangle.
Definition: PixelTriangle.h:233
T bottom() const
Returns the most bottom (including) position of this triangle.
Definition: PixelTriangle.h:266
const PixelPositionT< T > & point0() const
Returns the first corner point of this triangle.
Definition: PixelTriangle.h:227
const PixelPositionT< T > & point2() const
Returns the third corner point of this triangle.
Definition: PixelTriangle.h:239
T top() const
Returns the most top (including) position of this triangle.
Definition: PixelTriangle.h:252
T left() const
Returns the most left (including) position of this triangle.
Definition: PixelTriangle.h:245
This class implements functions allowing to create or to modify masks.
Definition: MaskCreator.h:33
static void denseContour2exclusiveMaskOffsets(const PixelContour &denseDistinctContour, IndexGroups32 &offsetGroups)
Determines the group of horizontal pixel offset locations for a given dense and distinct contour so t...
static void inclusiveMaskOffsets2inclusiveMask(IndexGroups32 &offsetGroups, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t maskValue)
Creates an (inclusive) 8 bit mask for a given group of horizontal pixel offset locations.
static void separations2mask(const uint32_t *separation, const unsigned int width, const unsigned int height, const unsigned int separationPaddingElements, const uint8_t *ids, const size_t numberIds, const uint8_t maskValue, uint8_t *mask, const unsigned int maskPaddingElements)
Creates an 8 bit mask from a given 1 channel 32 bit separation frame.
static void separation2mask(const uint32_t *separation, const unsigned int width, const unsigned int height, const unsigned int separationPaddingElements, const uint32_t id, uint8_t *mask, const unsigned int maskPaddingElements, const uint8_t maskValue=0x00)
Creates an 8 bit mask from a given 1 channel 32 bit separation frame.
static void denseContour2inclusiveMaskHotizontallyConvex(uint8_t *mask, const unsigned int width, const unsigned int height, const PixelPositions &densePixelPositions, const uint8_t maskValue)
Creates a binary 8 bit horizontally-convex (inclusive) mask from a given dense contour.
static void smoothMask(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int iterations, const unsigned int incrementValue)
Smooths a given 8 bit mask frame by adding additional outline-4 mask pixels with incrementing values ...
static void triangles2inclusiveMask(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT< T > *triangles, const size_t size, const uint8_t maskValue, Worker *worker=nullptr)
Creates a binary 8 bit mask for several given triangles, actually the triangles will be painted into ...
Definition: MaskCreator.h:490
static bool contour2inclusiveMaskByTriangulation(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour &simplifiedContour, const unsigned int maskValue, Worker *worker=nullptr, bool *triangulationForced=nullptr)
Creates a binary 8 bit (inclusive) mask for a given sparse or dense contour.
static void exclusiveMaskOffsets2exclusiveMaskXOR(IndexGroups32 &offsetGroups, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t xorReference)
Creates an (exclusive) 8 bit mask for a given group of horizontal pixel offset locations.
static void denseContour2inclusiveMask(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour &denseContour, const uint8_t maskValue)
Creates a binary 8 bit (inclusive) mask from a given dense and distinct contour.
Definition: MaskCreator.h:505
static void joinMasksSubset(const uint8_t *mask, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int targetPaddingElements, const uint8_t maskValue, const unsigned int firstRow, const unsigned int numberRows)
Joins two 8 bit masks with respect to a specific mask value.
static void denseContour2exclusiveMask(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour &denseContour, const uint8_t maskValue)
Creates a binary 8 bit (exclusive) mask from a given dense and distinct contour.
Definition: MaskCreator.h:523
static void denseContour2exclusiveMaskXOR(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour &denseContour, const uint8_t xorReference=0xFF)
Creates a binary 8 bit (exclusive) mask from a given dense and distinct contour.
Definition: MaskCreator.h:532
static void exclusiveMaskOffsets2exclusiveMask(IndexGroups32 &offsetGroups, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t maskValue)
Creates an (exclusive) 8 bit mask for a given group of horizontal pixel offset locations.
static void denseContour2inclusiveMaskXOR(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const PixelContour &denseContour, const uint8_t xorReference=0xFF)
Creates a binary 8 bit (inclusive) mask from a given dense and distinct contour.
Definition: MaskCreator.h:514
static void denseContour2inclusiveMaskOffsets(const PixelContour &denseDistinctContour, IndexGroups32 &offsetGroups)
Determines the group of horizontal pixel offset locations for a given dense and distinct contour so t...
static void inclusiveMaskOffsets2inclusiveMaskXOR(IndexGroups32 &offsetGroups, uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const uint8_t xorReference)
Creates an (inclusive) 8 bit mask for a given group of horizontal pixel offset locations.
static void triangles2inclusiveMaskSubset(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT< T > *triangles, const uint8_t maskValue, const unsigned int firstTriangle, const unsigned int numberTriangles)
Creates a binary 8 bit mask for a subset of several given triangles, actually the triangles will be p...
Definition: MaskCreator.h:557
static void triangle2inclusiveMask(uint8_t *mask, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const Advanced::PixelTriangleT< T > &triangle, const uint8_t maskValue)
Creates a binary 8 bit (inclusive) mask for one given triangle, actually the triangle is painted into...
static void joinMasks(const uint8_t *mask, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int maskPaddingElements, const unsigned int targetPaddingElements, const uint8_t maskValue=0x00, Worker *worker=nullptr)
Joins two 8 bit masks with respect to a specific mask value.
Definition: MaskCreator.h:541
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition: Caller.h:2876
static constexpr T minValue()
Returns the min scalar value.
Definition: Numeric.h:3250
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< Indices32 > IndexGroups32
Definition of a vector holding 32 bit indices, so we have groups of indices.
Definition: Base.h:102
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions (with positive coordinate values).
Definition: PixelPosition.h:48
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15