Ocean
Loading...
Searching...
No Matches
FrameFilterMean.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_MEAN_FILTER_H
9#define META_OCEAN_CV_FRAME_MEAN_FILTER_H
10
11#include "ocean/cv/CV.h"
13
14#include "ocean/base/Frame.h"
15#include "ocean/base/Worker.h"
16
17namespace Ocean
18{
19
20namespace CV
21{
22
23/**
24 * This class implements a mean frame filter.
25 * @ingroup cv
26 */
27class OCEAN_CV_EXPORT FrameFilterMean
28{
29 public:
30
31 /**
32 * Definition of different mean filter masks.
33 */
34 enum FilterMask : uint32_t
35 {
36 /// Invalid filter mask.
37 FM_INVALID = 0u,
38 /// One dimensional mean filter mask: 1/3 * [1 1 1].
39 FM_KERNEL_3 = 3u,
40 /// One dimensional mean filter mask: 1/5 * [1 1 1 1 1].
41 FM_KERNEL_5 = 5u
42 };
43
44 public:
45
46 /**
47 * Filters a given frame using a mean filter with arbitrary size by internally using a bordered integral image.
48 * @param source The source frame to be filtered
49 * @param target The target frame receiving the filtered frame
50 * @param window Size of the filter window in pixel, must be odd (actual size: window x window)
51 * @param worker Optional worker object to distribute the computation
52 * @return True, if succeeded
53 */
54 static bool filter(const Frame& source, Frame& target, const unsigned int window, Worker* worker = nullptr);
55
56 /**
57 * Filters a given frame using a mean filter with arbitrary size by internally using a bordered integral image.
58 * @param frame The frame to be filtered
59 * @param window Size of the filter window in pixel, must be odd (actual size: window x window)
60 * @param worker Optional worker object to distribute the computation
61 * @return True, if succeeded
62 */
63 static bool filter(Frame& frame, const unsigned int window, Worker* worker = nullptr);
64
65 /**
66 * Filters a given frame using a mean filter with arbitrary windows size by internally using a bordered integral image.
67 * @param source The source frame to be filtered, must be valid
68 * @param target The target frame receiving the filter result, must be valid
69 * @param width The width of source and target frame, in pixel, with range [1, infinity)
70 * @param height The height of source and target frame, in pixel, with range [1, infinity)
71 * @param window Size of the filter window in pixel, with range [1, infinity), must be odd (actual size: window x window)
72 * @param sourcePaddingElements The number of padding elements at the end of each source row, in elements, with range [0, infinity)
73 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
74 * @param worker Optional worker object to distribute the computation
75 * @tparam tChannels The number of frame channels, with range [1, infinity)
76 */
77 template <unsigned int tChannels>
78 static void filter8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
79
80 /**
81 * Filters a given frame using a mean filter with arbitrary windows size by internally using a bordered integral image.
82 * @param frame The frame to be filtered, must be valid
83 * @param width The width of source and target frame, in pixel, with range [1, infinity)
84 * @param height The height of source and target frame, in pixel, with range [1, infinity)
85 * @param window Size of the filter window in pixel, with range [1, infinity), must be odd (actual size: window x window)
86 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
87 * @param worker Optional worker object to distribute the computation
88 * @tparam tChannels The number of frame channels, with range [1, infinity)
89 */
90 template <unsigned int tChannels>
91 static void filter8BitPerChannel(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int framePaddingElements, Worker* worker = nullptr);
92
93 /**
94 * Filters a frame using a mean filter with arbitrary size by using a bordered integral image.
95 * The size of the integral image's border must be `window / 2`.<br>
96 * @param borderedIntegral The bordered integral image of the original image, with border `window / 2`, must be valid
97 * @param target The target frame receiving the filter result, must be valid
98 * @param width The width of the original image in pixel, with range [1, infinity)
99 * @param height The height of the original image in pixel, with range [1, infinity)
100 * @param window Size of the filter window in pixel, with range [1, infinity), must be odd (actual size: window x window)
101 * @param borderedIntegralPaddingElements The number of padding elements at the end of each integral image row, in elements, with range [0, infinity)
102 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
103 * @param worker Optional worker object to distribute the computation
104 * @tparam tChannels The number of channels the original frame (and the bordered integral image) has, with range [1, infinity)
105 */
106 template <unsigned int tChannels>
107 static void filterWithIntegral8BitPerChannel(const uint32_t* borderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, Worker* worker = nullptr);
108
109 protected:
110
111 /**
112 * Filters a subset of a frame using a mean filter with arbitrary size by using a bordered integral image.
113 * The size of the integral image's border must be `window / 2`.<br>
114 * @param borderedIntegral The bordered integral image of the original image, with border `window / 2`, must be valid
115 * @param target The target frame receiving the filter result, must be valid
116 * @param width The width of the original image in pixel, with range [1, infinity)
117 * @param height The height of the original image in pixel, with range [1, infinity)
118 * @param window Size of the filter window in pixel, with range [1, infinity), must be odd (actual size: window x window)
119 * @param borderedIntegralPaddingElements The number of padding elements at the end of each integral image row, in elements, with range [0, infinity)
120 * @param targetPaddingElements The number of padding elements at the end of each target row, in elements, with range [0, infinity)
121 * @param firstRow The first row to be handled, with range [0, height - 1]
122 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
123 * @tparam tChannels The number of channels the original frame (and the bordered integral image) has, with range [1, infinity)
124 */
125 template <unsigned int tChannels>
126 static void filterWithIntegral8BitPerChannelSubset(const uint32_t* borderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows);
127};
128
129template <unsigned int tChannels>
130void FrameFilterMean::filter8BitPerChannel(const uint8_t* source, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker* worker)
131{
132 static_assert(tChannels >= 1u, "Invalid channel number!");
133
134 ocean_assert(source != nullptr && target != nullptr);
135 ocean_assert(window % 2u == 1u);
136
137 const unsigned int border = window / 2u;
138
139 const unsigned int integralWidth = width + window;
140 const unsigned int integralHeight = height + window;
141
142 Frame integralFrame(FrameType(integralWidth, integralHeight, FrameType::genericPixelFormat<uint32_t, tChannels>(), FrameType::ORIGIN_UPPER_LEFT));
143 CV::IntegralImage::createBorderedImageMirror<uint8_t, uint32_t, tChannels>(source, integralFrame.data<uint32_t>(), width, height, border, sourcePaddingElements, integralFrame.paddingElements());
144
145 filterWithIntegral8BitPerChannel<tChannels>(integralFrame.constdata<uint32_t>(), target, width, height, window, integralFrame.paddingElements(), targetPaddingElements, worker);
146}
147
148template <unsigned int tChannels>
149void FrameFilterMean::filter8BitPerChannel(uint8_t* frame, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int framePaddingElements, Worker* worker)
150{
151 static_assert(tChannels >= 1u, "Invalid channel number!");
152
153 ocean_assert(frame != nullptr);
154 ocean_assert(window % 2u == 1u);
155
156 const unsigned int border = window / 2u;
157
158 const unsigned int integralWidth = width + window;
159 const unsigned int integralHeight = height + window;
160
161 Frame integralFrame(FrameType(integralWidth, integralHeight, FrameType::genericPixelFormat<uint32_t, tChannels>(), FrameType::ORIGIN_UPPER_LEFT));
162 CV::IntegralImage::createBorderedImageMirror<uint8_t, uint32_t, tChannels>(frame, integralFrame.data<uint32_t>(), width, height, border, framePaddingElements, integralFrame.paddingElements());
163
164 filterWithIntegral8BitPerChannel<tChannels>(integralFrame.constdata<uint32_t>(), frame, width, height, window, integralFrame.paddingElements(), framePaddingElements, worker);
165}
166
167template <unsigned int tChannels>
168inline void FrameFilterMean::filterWithIntegral8BitPerChannel(const uint32_t* borderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, Worker* worker)
169{
170 static_assert(tChannels >= 1u, "Invalid channel number!");
171
172 ocean_assert(borderedIntegral != nullptr && target != nullptr);
173 ocean_assert(window % 2u == 1u);
174
175 if (worker)
176 {
177 worker->executeFunction(Worker::Function::createStatic(&FrameFilterMean::filterWithIntegral8BitPerChannelSubset<tChannels>, borderedIntegral, target, width, height, window, borderedIntegralPaddingElements, targetPaddingElements, 0u, 0u), 0u, height);
178 }
179 else
180 {
181 filterWithIntegral8BitPerChannelSubset<tChannels>(borderedIntegral, target, width, height, window, borderedIntegralPaddingElements, targetPaddingElements, 0u, height);
182 }
183}
184
185template <unsigned int tChannels>
186void FrameFilterMean::filterWithIntegral8BitPerChannelSubset(const uint32_t* borderedIntegral, uint8_t* target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
187{
188 ocean_assert(borderedIntegral != nullptr && target != nullptr);
189 ocean_assert(window % 2u == 1u);
190
191 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
192
193 const unsigned int borderedIntegralStrideElements = (width + window) * tChannels + borderedIntegralPaddingElements; // window as the integral image has a border of size window/2, and one extra row/column
194 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
195
196 const unsigned int integralSkipElements = window * tChannels + borderedIntegralPaddingElements;
197
198 const unsigned int area = window * window;
199 const unsigned int area_2 = (area + 1u) / 2u;
200
201 const uint32_t* integralTopLeft = borderedIntegral + firstRow * borderedIntegralStrideElements;
202 const uint32_t* integralBottomLeft = borderedIntegral + (firstRow + window) * borderedIntegralStrideElements;
203
204 const uint32_t* integralTopRight = integralTopLeft + window * tChannels;
205 const uint32_t* integralBottomRight = integralBottomLeft + window * tChannels;
206
207 uint8_t* targetRow = target + firstRow * targetStrideElements;
208
209 for (unsigned int y = 0u; y < numberRows; ++y)
210 {
211 ocean_assert((integralTopLeft - borderedIntegral) % borderedIntegralStrideElements == 0u);
212 ocean_assert((integralBottomLeft - borderedIntegral) % borderedIntegralStrideElements == 0u);
213
214 for (unsigned int x = 0u; x < width; ++x)
215 {
216 for (unsigned int n = 0u; n < tChannels; ++n)
217 {
218 ocean_assert((*integralTopLeft - *integralTopRight - *integralBottomLeft + *integralBottomRight + area_2) / area <= 255u);
219
220 *targetRow++ = uint8_t((*integralTopLeft++ - *integralTopRight++ - *integralBottomLeft++ + *integralBottomRight++ + area_2) / area);
221 }
222 }
223
224 integralTopLeft += integralSkipElements;
225 integralBottomLeft += integralSkipElements;
226
227 integralTopRight += integralSkipElements;
228 integralBottomRight += integralSkipElements;
229
230 targetRow += targetPaddingElements;
231 }
232}
233
234}
235
236}
237
238#endif // META_OCEAN_CV_FRAME_MEAN_FILTER_H
This class implements a mean frame filter.
Definition FrameFilterMean.h:28
FilterMask
Definition of different mean filter masks.
Definition FrameFilterMean.h:35
static void filter8BitPerChannel(const uint8_t *source, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int sourcePaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Filters a given frame using a mean filter with arbitrary windows size by internally using a bordered ...
Definition FrameFilterMean.h:130
static bool filter(const Frame &source, Frame &target, const unsigned int window, Worker *worker=nullptr)
Filters a given frame using a mean filter with arbitrary size by internally using a bordered integral...
static void filterWithIntegral8BitPerChannel(const uint32_t *borderedIntegral, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, Worker *worker=nullptr)
Filters a frame using a mean filter with arbitrary size by using a bordered integral image.
Definition FrameFilterMean.h:168
static void filterWithIntegral8BitPerChannelSubset(const uint32_t *borderedIntegral, uint8_t *target, const unsigned int width, const unsigned int height, const unsigned int window, const unsigned int borderedIntegralPaddingElements, const unsigned int targetPaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Filters a subset of a frame using a mean filter with arbitrary size by using a bordered integral imag...
Definition FrameFilterMean.h:186
static bool filter(Frame &frame, const unsigned int window, Worker *worker=nullptr)
Filters a given frame using a mean filter with arbitrary size by internally using a bordered integral...
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:1808
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
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
@ 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 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