Ocean
FrameConverterThreshold.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_FRAME_CONVERTER_THRESHOLD_H
9 #define META_OCEAN_CV_FRAME_CONVERTER_THRESHOLD_H
10 
11 #include "ocean/cv/CV.h"
13 
14 #include "ocean/base/Worker.h"
15 
16 namespace Ocean
17 {
18 
19 namespace CV
20 {
21 
22 /**
23  * This class implements frame converters dividing a frame by application of a threshold.
24  * @ingroup cv
25  */
26 class OCEAN_CV_EXPORT FrameConverterThreshold : public FrameConverter
27 {
28  public:
29 
30  /**
31  * Converts an 8 bit (grayscale) frame into a binary frame using a threshold value.
32  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.
33  * @param buffer Source and target frame buffer, must be valid
34  * @param width The width of the frame in pixel, with range [1, infinity)
35  * @param height The height of the frame in pixel, with range [1, infinity)
36  * @param bufferPaddingElements The number of padding elements at the end of each buffer row, in elements, with range [0, infinity)
37  * @param threshold The threshold dividing the frame into black and white, with range [1, 255]
38  * @param worker Optional worker used to distribute the CPU load
39  */
40  static inline void convertY8ToB8(uint8_t* buffer, const unsigned int width, const unsigned int height, const unsigned int bufferPaddingElements, const uint8_t threshold, Worker* worker = nullptr);
41 
42  /**
43  * Converts an 8 bit gray scale frame into a second binary frame using a threshold.
44  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.
45  * @param source The source frame buffer, must be valid
46  * @param target The target frame buffer, must be valid
47  * @param width The width of the frame in pixel, with range [1, infinity)
48  * @param height The height of the frame in pixel, with range [1, infinity)
49  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
50  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
51  * @param threshold The threshold dividing the frame into black and white, with range [1, 255]
52  * @param worker Optional worker used to distribute the CPU load
53  */
54  static inline void convertY8ToB8(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t threshold, Worker* worker = nullptr);
55 
56  /**
57  * Converts a gray scale frame into a second binary frame using a relative threshold and a kernel size.
58  * Instead using the gray scale frame only, additional the bordered integral image of the gray scale image is used.<br>
59  * The resulting binary frame uses a relative threshold resulting in better black-white borders.<br>
60  * Beware: The specified kernel size must have an odd value.<br>
61  * Beware: The border size of the integral image must have size: (kernel - 1) / 2 be the same as the used kernel size.<br>
62  * The corresponding integral image can be created with IntegralImage::createBorderedImage().<br>
63  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.<br>
64  * Compare: Adaptive Thresholding Using the Integral Image, Bradley
65  * @param source The source frame buffer of the normal 8 bit gray scale image, must be valid
66  * @param sourceBorderedIntegral Source frame buffer of the integral image, must be valid
67  * @param target The target frame buffer, must be valid
68  * @param width The width of the frame in pixel, with range [1, infinity)
69  * @param height The height of the frame in pixel, with range [1, infinity)
70  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
71  * @param sourceBorderedIntegralPaddingElements The number of padding elements at the end of each source integral row, in elements, with range [0, infinity)
72  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
73  * @param kernelSize Size of the kernel used for adaptive thresholding, the kernel size must be: (integralBorder * 2) + 1
74  * @param threshold The threshold (percentage) dividing the frame adaptive into black and white, with range (0, 1)
75  * @param worker Optional worker used to distribute the CPU load
76  * @see IntegralImage::createBorderedImage().
77  */
78  static inline void convertBorderedY8ToB8(const uint8_t* source, const uint32_t* sourceBorderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int sourceBorderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int kernelSize, const float threshold, Worker* worker = nullptr);
79 
80  /**
81  * Calculate binarization threshold for a given image by application of the Otsu algorithm.
82  * The implementation follows the work of N. Otsu: "A threshold selection method from gray-level histograms", IEEE Trans. Systems, Man and Cybernetics 9(1), pp. 62-66, 1979.
83  * @param source The source frame buffer, must be valid
84  * @param width The width of the frame in pixel, with range [1, infinity)
85  * @param height The height of the frame in pixel, with range [1, infinity)
86  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
87  * @param worker Optional worker object to distribute the computational load
88  * @return Returns binarization threshold, with range [0, 255]
89  * @see convertY8ToB8()
90  *
91  * The following tutorial shows how this function may be used:
92  * @code
93  * bool applyOtsu(const Frame& source, Frame& target, Worker* worker)
94  * {
95  * Frame yFrame;
96  * if (!CV::FrameConverter::Comfort::convert(source, FrameType::FORMAT_Y8, yFrame, CV::FrameConverter::CP_AVOID_COPY_IF_POSSIBLE, worker))
97  * {
98  * ocean_assert(false && "Unsupported pixel format!");
99  * return false;
100  * }
101  *
102  * const uint8_t otsuThreshold = CV::FrameConverterThreshold::calculateOtsuThreshold(yFrame.constdata<uint8_t>(), yFrame.width(), yFrame.height(), yFrame.paddingElements(), worker);
103  *
104  * if (!target.set(yFrame.frameType(), true, true))
105  * {
106  * return false;
107  * }
108  *
109  * CV::FrameConverterThreshold::convertY8ToB8(yFrame.constdata<uint8_t>(), target.data<uint8_t>(), yFrame.width(), yFrame.height(), yFrame.paddingElements(), target.paddingElements(), otsuThreshold, worker);
110  *
111  * return true;
112  * }
113  * @endcode
114  */
115  static uint8_t calculateOtsuThreshold(const uint8_t* source, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, Worker* worker = nullptr);
116 
117  protected:
118 
119  /**
120  * Converts an 8 bit gray scale frame into a binary frame using a threshold.
121  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.
122  * @param buffer Source and target frame buffer, must be valid
123  * @param width The width of the frame in pixel, with range [1, infinity)
124  * @param height The height of the frame in pixel, with range [1, infinity)
125  * @param bufferPaddingElements The number of padding elements at the end of each buffer row, in elements, with range [0, infinity)
126  * @param threshold The threshold dividing the frame into black and white, with range [0, 255]
127  * @param firstRow First (including) row to convert, with range [0, height)
128  * @param numberRows Number of rows to convert, with range [1, height - firstRow]
129  */
130  static void convertY8ToB8Subset(uint8_t* buffer, const unsigned int width, const unsigned int height, const unsigned int bufferPaddingElements, const uint8_t threshold, const unsigned int firstRow, const unsigned int numberRows);
131 
132  /**
133  * Converts an 8 bit gray scale frame into a second binary frame using a threshold.
134  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.
135  * @param source The source frame buffer, must be valid
136  * @param target The target frame buffer, must be valid
137  * @param width The width of the frame in pixel, with range [1, infinity)
138  * @param height The height of the frame in pixel, with range [1, infinity)
139  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
140  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
141  * @param threshold The threshold dividing the frame into black and white, with range [0, 255]
142  * @param firstRow First (including) row to convert, with range [0, height)
143  * @param numberRows Number of rows to convert, with range [1, height - firstRow]
144  */
145  static void convertY8ToB8Subset(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t threshold, const unsigned int firstRow, const unsigned int numberRows);
146 
147  /**
148  * Converts a gray scale frame into a second binary frame using a relative threshold and a kernel size.
149  * Instead using the gray scale frame only, additional the bordered integral image of the gray scale image is used.<br>
150  * The resulting binary frame uses a relative threshold resulting in better black-white borders.<br>
151  * Beware: The specified kernel size must have an odd value.<br>
152  * Beware: The border size of the integral image must have size: (kernel - 1) / 2 be the same as the used kernel size.<br>
153  * The corresponding integral image can be created with IntegralImage::createBorderedImage().<br>
154  * The resulting target pixel values will be 0 for all input values smaller than the specified threshold value and 255 for all input values equal or larger than the specified threshold value.<br>
155  * Compare: Adaptive Thresholding Using the Integral Image, Bradley
156  * @param source The source frame buffer of the normal 8 bit gray scale image
157  * @param sourceBorderedIntegral Source frame buffer of the integral image
158  * @param target The target frame buffer, must be valid
159  * @param width The width of the frame in pixel, with range [1, infinity)
160  * @param height The height of the frame in pixel, with range [1, infinity)
161  * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
162  * @param sourceBorderedIntegralPaddingElements The number of padding elements at the end of each source integral row, in elements, with range [0, infinity)
163  * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
164  * @param kernelSize Size of the kernel used for adaptive thresholding, the kernel size must be: (integralBorder * 2) + 1
165  * @param threshold The threshold (percentage) dividing the frame adaptive into black and white, with range (0, 1)
166  * @param firstRow First (including) row to convert, with range [0, height)
167  * @param numberRows Number of rows to convert, with range [1, height - firstRow]
168  * @see IntegralImage::createBorderedImage().
169  */
170  static void convertBorderedY8ToB8Subset(const uint8_t* source, const uint32_t* sourceBorderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int sourceBorderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int kernelSize, const float threshold, const unsigned int firstRow, const unsigned int numberRows);
171 };
172 
173 inline void FrameConverterThreshold::convertY8ToB8(uint8_t* buffer, const unsigned int width, const unsigned int height, const unsigned int bufferPaddingElements, const uint8_t threshold, Worker* worker)
174 {
175  ocean_assert(buffer != nullptr);
176  ocean_assert(width >= 1u && height >= 1u);
177  ocean_assert(threshold >= 1u);
178 
179  if (worker)
180  {
181  worker->executeFunction(Worker::Function::createStatic(&FrameConverterThreshold::convertY8ToB8Subset, buffer, width, height, bufferPaddingElements, threshold, 0u, 0u), 0u, height);
182  }
183  else
184  {
185  convertY8ToB8Subset(buffer, width, height, bufferPaddingElements, threshold, 0u, height);
186  }
187 }
188 
189 inline void FrameConverterThreshold::convertY8ToB8(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t threshold, Worker* worker)
190 {
191  ocean_assert(source != nullptr && target != nullptr);
192  ocean_assert(width >= 1u && height >= 1u);
193  ocean_assert(threshold >= 1u);
194 
195  if (worker)
196  {
197  worker->executeFunction(Worker::Function::createStatic(&FrameConverterThreshold::convertY8ToB8Subset, source, target, width, height, sourcePaddingElements, targetPaddingElements, threshold, 0u, 0u), 0u, height);
198  }
199  else
200  {
201  convertY8ToB8Subset(source, target, width, height, sourcePaddingElements, targetPaddingElements, threshold, 0u, height);
202  }
203 }
204 
205 inline void FrameConverterThreshold::convertBorderedY8ToB8(const uint8_t* source, const uint32_t* sourceBorderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int sourceBorderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int kernelSize, const float threshold, Worker* worker)
206 {
207  if (worker)
208  {
209  worker->executeFunction(Worker::Function::createStatic(&convertBorderedY8ToB8Subset, source, sourceBorderedIntegral, target, width, height, sourcePaddingElements, sourceBorderedIntegralPaddingElements, targetPaddingElements, kernelSize, threshold, 0u, 0u), 0, height);
210  }
211  else
212  {
213  convertBorderedY8ToB8Subset(source, sourceBorderedIntegral, target, width, height, sourcePaddingElements, sourceBorderedIntegralPaddingElements, targetPaddingElements, kernelSize, threshold, 0u, height);
214  }
215 }
216 
217 }
218 
219 }
220 
221 #endif // META_OCEAN_CV_FRAME_CONVERTER_THRESHOLD_H
This is the base class for all frame converter classes.
Definition: FrameConverter.h:32
This class implements frame converters dividing a frame by application of a threshold.
Definition: FrameConverterThreshold.h:27
static void convertY8ToB8(uint8_t *buffer, const unsigned int width, const unsigned int height, const unsigned int bufferPaddingElements, const uint8_t threshold, Worker *worker=nullptr)
Converts an 8 bit (grayscale) frame into a binary frame using a threshold value.
Definition: FrameConverterThreshold.h:173
static void convertBorderedY8ToB8(const uint8_t *source, const uint32_t *sourceBorderedIntegral, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int sourceBorderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int kernelSize, const float threshold, Worker *worker=nullptr)
Converts a gray scale frame into a second binary frame using a relative threshold and a kernel size.
Definition: FrameConverterThreshold.h:205
static uint8_t calculateOtsuThreshold(const uint8_t *source, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, Worker *worker=nullptr)
Calculate binarization threshold for a given image by application of the Otsu algorithm.
static void convertY8ToB8Subset(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, const uint8_t threshold, const unsigned int firstRow, const unsigned int numberRows)
Converts an 8 bit gray scale frame into a second binary frame using a threshold.
static void convertY8ToB8Subset(uint8_t *buffer, const unsigned int width, const unsigned int height, const unsigned int bufferPaddingElements, const uint8_t threshold, const unsigned int firstRow, const unsigned int numberRows)
Converts an 8 bit gray scale frame into a binary frame using a threshold.
static void convertBorderedY8ToB8Subset(const uint8_t *source, const uint32_t *sourceBorderedIntegral, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int sourcePaddingElements, const unsigned int sourceBorderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int kernelSize, const float threshold, const unsigned int firstRow, const unsigned int numberRows)
Converts a gray scale frame into a second binary frame using a relative threshold and a kernel size.
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 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.
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15