Ocean
MaskAnalyzer.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_MASK_ANALYZER_H
9 #define META_OCEAN_CV_MASK_ANALYZER_H
10 
11 #include "ocean/cv/CV.h"
12 
13 #include "ocean/base/Frame.h"
14 #include "ocean/base/Worker.h"
15 
17 
18 namespace Ocean
19 {
20 
21 namespace CV
22 {
23 
24 /**
25  * This class implements basic maks analyzing functions.
26  * More advanced mask analyzing functions are available in CV::Segmentation::MaskAnalyzer.
27  * @ingroup cv
28  */
29 class OCEAN_CV_EXPORT MaskAnalyzer
30 {
31  public:
32 
33  /**
34  * Detects the smallest axis-aligned bounding box enclosing all isolated mask islands in a binary (but 8-bit) mask frame.
35  * @param mask The 8 bit mask frame in which the enclosing bounding box will be determined, must be valid
36  * @param width The width of the mask frame in pixel, with range [1, infinity)
37  * @param height The height of the mask frame in pixel, with range [1, infinity)
38  * @param nonMaskPixel The value of pixels not part of the mask, all other values will be mask pixels, with range [0, infinity)
39  * @param maskPaddingElements The number of padding elements at the end of each mask row, with range [0, infinity)
40  * @return Resulting mask bounding box, invalid if no mask could be found
41  * @see CV::Segmentation::MaskAnalyzer::detectBoundingBoxes().
42  */
43  static PixelBoundingBox detectBoundingBox(const uint8_t* mask, const unsigned int width, const unsigned int height, const uint8_t nonMaskPixel, const unsigned int maskPaddingElements);
44 
45  /**
46  * Detects the smallest axis-aligned bounding box enclosing all isolated mask islands inside a given mask frame using a rough approximation of the bounding box.
47  * @param mask The 8 bit mask frame in which the bounding box will be determined, must be valid
48  * @param width The width of the mask frame in pixel, with range [1, infinity)
49  * @param height The height of the mask frame in pixel, with range [1, infinity)
50  * @param rough Rough approximation of the final bounding box, must be valid
51  * @param maxUncertainty Maximal pixel uncertainty of the rough box guess, with range [1, infinity)
52  * @param nonMaskPixel The value of pixel not part of the mask, all other values will be mask pixels, with range [0, infinity)
53  * @param maskPaddingElements The number of padding elements at the end of each mask row, with range [0, infinity)
54  * @return Resulting mask bounding box, invalid if no mask could be found
55  */
56  static PixelBoundingBox detectBoundingBox(const uint8_t* const mask, const unsigned int width, const unsigned int height, const PixelBoundingBox& rough, const unsigned int maxUncertainty, const uint8_t nonMaskPixel = 0xFFu, const unsigned int maskPaddingElements = 0u);
57 
58  /**
59  * Detects the smallest bounding box enclosing all opaque pixels in a given frame.
60  * @param frame The frame in which the bounding box enclosing all opaque pixels is determined, must be valid
61  * @param width The width of the frame in pixel, with range [1, infinity)
62  * @param height The height of the frame in pixel, with range [1, infinity)
63  * @param alphaChannelIndex The index of the alpha channel, with range [0, channels)
64  * @param channels The number of frame channels, with range [1, infinity)
65  * @param fullTransparentValue The alpha pixel value of a full transparent pixel
66  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
67  * @param worker Optional worker object to distribute the computation
68  * @return The smallest bounding box enclosing all opaque pixels, an invalid bounding box if the frames does not contain an opaque pixel
69  * @tparam T Data type of each pixel channel value
70  */
71  template <typename T>
72  static PixelBoundingBox detectOpaqueBoundingBox(const T* frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, Worker* worker = nullptr);
73 
74  /**
75  * Detects the smallest bounding box of opaque pixels in a given frame.
76  * @param frame The frame in the opaque pixels are determined
77  * @param transparentIs0xFF True, if 0xFF is interpreted as a full transparent pixel
78  * @param worker Optional worker object to distribute the computation
79  * @return Resulting smallest bounding box, an invalid bounding box if no opaque pixel has been found
80  */
81  static PixelBoundingBox detectOpaqueBoundingBox(const Frame& frame, const bool transparentIs0xFF, Worker* worker = nullptr);
82 
83  /**
84  * Returns whether a mask frame has at least one pixel with a specific mask value.
85  * @param mask The 8 bit mask frame in which the pixel value is sought, must be valid
86  * @param width The width of the mask frame in pixel, with range [1, infinity)
87  * @param height The height of the mask frame in pixel, with range [1, infinity)
88  * @param value The value to be sought, with range [0, 255]
89  * @param maskPaddingElements The number of padding elements at the end of each mask row, in elements, with range [0, infinity)
90  * @param boundingBox Optional bounding box to speedup the computation, must fit into the given frame if defined
91  * @return True, if at least one mask pixel has the specified value
92  */
93  static inline bool hasValue(const uint8_t* mask, const unsigned int width, const unsigned int height, const uint8_t value, const unsigned int maskPaddingElements, const PixelBoundingBox& boundingBox = CV::PixelBoundingBox());
94 
95  protected:
96 
97  /**
98  * Detects the smallest bounding box enclosing all opaque pixels in a subset of a given frame.
99  * @param frame The frame in which the bounding box enclosing all opaque pixels is determined, must be valid
100  * @param width The width of the frame in pixel, with range [1, infinity)
101  * @param height The height of the frame in pixel, with range [1, infinity)
102  * @param alphaChannelIndex The index of the alpha channel, with range [0, channels - 1]
103  * @param channels The number of frame channels, with range [1, infinity)
104  * @param fullTransparentValue The alpha pixel value of a full transparent pixel
105  * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
106  * @param left Resulting left bounding box position
107  * @param top Resulting top bounding box position
108  * @param right Resulting right bounding box position
109  * @param bottom Resulting bottom bounding box position
110  * @param lock Optional lock if this function is executed distributed within several threads
111  * @param firstRow First row to be handled
112  * @param numberRows Number of rows to be handled
113  * @tparam T Data type of each pixel channel value
114  */
115  template <typename T>
116  static void detectOpaqueBoundingBoxSubset(const T* frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, unsigned int* left, unsigned int* top, unsigned int* right, unsigned int* bottom, Lock* lock, const unsigned int firstRow, const unsigned int numberRows);
117 };
118 
119 template <typename T>
120 PixelBoundingBox MaskAnalyzer::detectOpaqueBoundingBox(const T* frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, Worker* worker)
121 {
122  ocean_assert(frame != nullptr);
123  ocean_assert(channels != 0u);
124  ocean_assert(alphaChannelIndex < channels);
125 
126  unsigned int left = (unsigned int)(-1);
127  unsigned int top = (unsigned int)(-1);
128  unsigned int right = 0u;
129  unsigned int bottom = 0u;
130 
131  if (worker)
132  {
133  Lock lock;
134  worker->executeFunction(Worker::Function::createStatic(&MaskAnalyzer::detectOpaqueBoundingBoxSubset<T>, frame, width, height, alphaChannelIndex, channels, fullTransparentValue, framePaddingElements, &left, &top, &right, &bottom, &lock, 0u, 0u), 0u, height, 12u, 13u, 20u);
135  }
136  else
137  {
138  detectOpaqueBoundingBoxSubset<T>(frame, width, height, alphaChannelIndex, channels, fullTransparentValue, framePaddingElements, &left, &top, &right, &bottom, nullptr, 0u, height);
139  }
140 
141  return PixelBoundingBox(left, top, right, bottom);
142 }
143 
144 template <typename T>
145 void MaskAnalyzer::detectOpaqueBoundingBoxSubset(const T* frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, unsigned int* left, unsigned int* top, unsigned int* right, unsigned int* bottom, Lock* lock, const unsigned int firstRow, const unsigned int numberRows)
146 {
147  ocean_assert(frame != nullptr);
148  ocean_assert(alphaChannelIndex < channels);
149  ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
150 
151  const unsigned int frameStrideElements = width * channels + framePaddingElements;
152 
153  unsigned int localLeft = (unsigned int)(-1);
154  unsigned int localRight = 0u;
155  unsigned int localTop = (unsigned int)(-1);
156  unsigned int localBottom = 0u;
157 
158  for (unsigned int y = firstRow; y < firstRow + numberRows; ++y)
159  {
160  const T* frameRow = frame + y * frameStrideElements + alphaChannelIndex;
161 
162  for (unsigned int x = 0u; x < width; ++x)
163  {
164  if (*frameRow != fullTransparentValue)
165  {
166  if (x < localLeft)
167  {
168  localLeft = x;
169  }
170 
171  if (x > localRight)
172  {
173  localRight = x;
174  }
175 
176  if (y < localTop)
177  {
178  localTop = y;
179  }
180 
181  if (y > localBottom)
182  {
183  localBottom = y;
184  }
185  }
186 
187  frameRow += channels;
188  }
189  }
190 
191  const OptionalScopedLock scopedLock(lock);
192 
193  *left = min(*left, localLeft);
194  *top = min(*top, localTop);
195 
196  *right = max(*right, localRight);
197  *bottom = max(*bottom, localBottom);
198 }
199 
200 inline bool MaskAnalyzer::hasValue(const uint8_t* mask, const unsigned int width, const unsigned int height, const uint8_t value, const unsigned int maskPaddingElements, const PixelBoundingBox& boundingBox)
201 {
202  ocean_assert(mask != nullptr && width != 0u && height != 0u);
203 
204  const Frame maskFrame(FrameType(width, height, FrameType::FORMAT_Y8, FrameType::ORIGIN_UPPER_LEFT), mask, Frame::CM_USE_KEEP_LAYOUT, maskPaddingElements);
205 
206  const Frame::PixelType<uint8_t, 1u> pixelValue = {{value}};
207 
208  if (boundingBox.isValid())
209  {
210  return maskFrame.subFrame(boundingBox.left(), boundingBox.top(), boundingBox.width(), boundingBox.height(), Frame::CM_USE_KEEP_LAYOUT).containsValue<uint8_t, 1u>(pixelValue);
211  }
212 
213  return maskFrame.containsValue<uint8_t, 1u>(pixelValue);
214 }
215 
216 }
217 
218 }
219 
220 #endif // META_OCEAN_CV_MASK_ANALYZER_H
This class implements basic maks analyzing functions.
Definition: MaskAnalyzer.h:30
static PixelBoundingBox detectBoundingBox(const uint8_t *mask, const unsigned int width, const unsigned int height, const uint8_t nonMaskPixel, const unsigned int maskPaddingElements)
Detects the smallest axis-aligned bounding box enclosing all isolated mask islands in a binary (but 8...
static PixelBoundingBox detectOpaqueBoundingBox(const Frame &frame, const bool transparentIs0xFF, Worker *worker=nullptr)
Detects the smallest bounding box of opaque pixels in a given frame.
static PixelBoundingBox detectBoundingBox(const uint8_t *const mask, const unsigned int width, const unsigned int height, const PixelBoundingBox &rough, const unsigned int maxUncertainty, const uint8_t nonMaskPixel=0xFFu, const unsigned int maskPaddingElements=0u)
Detects the smallest axis-aligned bounding box enclosing all isolated mask islands inside a given mas...
static bool hasValue(const uint8_t *mask, const unsigned int width, const unsigned int height, const uint8_t value, const unsigned int maskPaddingElements, const PixelBoundingBox &boundingBox=CV::PixelBoundingBox())
Returns whether a mask frame has at least one pixel with a specific mask value.
Definition: MaskAnalyzer.h:200
static PixelBoundingBox detectOpaqueBoundingBox(const T *frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, Worker *worker=nullptr)
Detects the smallest bounding box enclosing all opaque pixels in a given frame.
Definition: MaskAnalyzer.h:120
static void detectOpaqueBoundingBoxSubset(const T *frame, const unsigned int width, const unsigned int height, const unsigned int alphaChannelIndex, const unsigned int channels, const T fullTransparentValue, const unsigned int framePaddingElements, unsigned int *left, unsigned int *top, unsigned int *right, unsigned int *bottom, Lock *lock, const unsigned int firstRow, const unsigned int numberRows)
Detects the smallest bounding box enclosing all opaque pixels in a subset of a given frame.
Definition: MaskAnalyzer.h:145
T left() const
Returns the left (including) pixel position of this bounding box.
Definition: PixelBoundingBox.h:416
unsigned int width() const
Returns the width (the number of horizontal including pixels) of this bounding box.
Definition: PixelBoundingBox.h:482
bool isValid() const
Returns whether this bounding box covers a valid pixel area.
Definition: PixelBoundingBox.h:577
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
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
This class implements Ocean's image class.
Definition: Frame.h:1792
typename Ocean::DataType< T, tChannels >::Type PixelType
Definition of a data type storing all channel values of one pixel in an array.
Definition: Frame.h:2311
Frame subFrame(const unsigned int subFrameLeft, const unsigned int subFrameTop, const unsigned int subFrameWidth, const unsigned int subFrameHeight, const CopyMode copyMode=CM_USE_KEEP_LAYOUT) const
Returns a sub-frame of this frame.
@ CM_USE_KEEP_LAYOUT
The source memory is used only, no copy is created, the padding layout is preserved.
Definition: Frame.h:1801
bool containsValue(const PixelType< T, tPlaneChannels > &planePixelValue, const unsigned int planeIndex=0u) const
Returns whether the frame (one plane) contains a specified pixel value.
Definition: Frame.h:3924
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 recursive lock object.
Definition: Lock.h:31
This class implements an optional recursive scoped lock object locking the lock object only if it's d...
Definition: Lock.h:325
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.
PixelBoundingBoxT< unsigned int > PixelBoundingBox
Definition of the default PixelBoundingBox object with data type allowing only positive coordinate va...
Definition: PixelBoundingBox.h:21
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15