Ocean
Loading...
Searching...
No Matches
FrameFilter.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_FILTER_H
9#define META_OCEAN_CV_FRAME_FILTER_H
10
11#include "ocean/cv/CV.h"
12
13#include "ocean/base/DataType.h"
14#include "ocean/base/Worker.h"
15
16#include "ocean/math/Numeric.h"
17
18namespace Ocean
19{
20
21namespace CV
22{
23
24/**
25 * This class implements the base class for all filter.
26 * @ingroup cv
27 */
28class OCEAN_CV_EXPORT FrameFilter
29{
30 public:
31
32 /**
33 * Determines the per-pixel magnitude of a frame.
34 * @param frame The input frame for which the magnitude will be determined, must be valid
35 * @param magnitude The resulting magnitude frame, must be valid
36 * @param width The width of the input (and magnitude) frame, in pixels, with range [1, infinity)
37 * @param height The height of the input (and magnitude) frame, in pixels, with range [1, infinity)
38 * @param channels The number of channels the frame has, with range [2, infinity)
39 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
40 * @param magnitudePaddingElements The number of padding elements at the end of each magnitude row, in elements, with range [0, infinity)
41 * @param worker The worker object to distribute the computation
42 * @tparam T The data type of the frame pixel channel
43 * @tparam TMagnitude The data type of the magnitude, ensure that the magnitude of 'T' (over all channels) fits into 'TMagnitude'
44 */
45 template <typename T, typename TMagnitude>
46 static void magnitude(const T* frame, TMagnitude* magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, Worker* worker = nullptr);
47
48 /**
49 * Normalizes a given value with a template-based normalization factor.
50 * This function will create a wrong rounded normalization result for extremely large 32bit and 64bit integers if the value is within tNormalizationDenominator/2 to the value range.<br>
51 * Thus, for integers and if 'tRoundedNormalization == true', the value range for valid rounded normalization results is:
52 * <pre>
53 * int32_t: [-2147483648 + tNormalizationDenominator/2, 2147483647 - tNormalizationDenominator/2]
54 * uint32_t: [0, 4294967295 - tNormalizationDenominator/2]
55
56 * int64_t: [-9223372036854775808 + tNormalizationDenominator/2, 9223372036854775807 - tNormalizationDenominator/2]
57 * uint64_t: [0, 18446744073709551615 - tNormalizationDenominator/2]
58 * </pre>
59 * @param value The value to be normalized
60 * @return The normalized value 'value / tNormalization'
61 * @tparam T The data type of the value to normalize, either an integer value or a floating point value
62 * @tparam tNormalizationDenominator The normalization factor to be applied, with range [1, infinity)
63 * @tparam tRoundedNormalization True, to apply a rounded normalization; False, to apply a normalization without rounding (ignored for floating point values)
64 * @see normalizeValueSlow().
65 */
66 template <typename T, T tNormalizationDenominator, bool tRoundedNormalization>
67 static inline T normalizeValue(const T& value);
68
69 /**
70 * Normalizes a given value with a template-based normalization factor.
71 * This function does not provide wrong normalization results for extremely large 32bit and 64bit integers if 'tRoundedNormalization == true', but is also slower.
72 * @param value The value to be normalized
73 * @return The normalized value 'value / tNormalization'
74 * @tparam T The data type of the value to normalize, either an integer value or a floating point value
75 * @tparam tNormalizationDenominator The normalization factor to be applied, with range [1, infinity)
76 * @tparam tRoundedNormalization True, to apply a rounded normalization; False, to apply a normalization without rounding (ignored for floating point values)
77 * @see normalizeValue().
78 */
79 template <typename T, T tNormalizationDenominator, bool tRoundedNormalization>
80 static inline T normalizeValueSlow(const T& value);
81
82 protected:
83
84 /**
85 * Determines the per-pixel magnitude for a subset of a frame.
86 * @param frame The input frame for which the magnitude will be determined, must be valid
87 * @param magnitude The resulting magnitude frame, must be valid
88 * @param width The width of the input (and magnitude) frame, in pixels, with range [1, infinity)
89 * @param height The height of the input (and magnitude) frame, in pixels, with range [1, infinity)
90 * @param channels The number of channels the frame has, with range [2, infinity)
91 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
92 * @param magnitudePaddingElements The number of padding elements at the end of each magnitude row, in elements, with range [0, infinity)
93 * @param firstRow The first row to be handled, with range [0, height - 1]
94 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
95 * @tparam T The data type of the frame pixel channel
96 * @tparam TMagnitude The data type of the magnitude, ensure that the magnitude of 'T' (over all channels) fits into 'TMagnitude'
97 */
98 template <typename T, typename TMagnitude>
99 static void magnitudeSubset(const T* frame, TMagnitude* magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, const unsigned int firstRow, const unsigned int numberRows);
100
101 /**
102 * Determines the per-pixel magnitude for a subset of a frame.
103 * This function applies a lookup-based sqrt calculation.
104 * @param frame The input frame for which the magnitude will be determined, must be valid
105 * @param magnitude The resulting magnitude frame, must be valid
106 * @param width The width of the input (and magnitude) frame, in pixels, with range [1, infinity)
107 * @param height The height of the input (and magnitude) frame, in pixels, with range [1, infinity)
108 * @param channels The number of channels the frame has, with range [2, infinity)
109 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
110 * @param magnitudePaddingElements The number of padding elements at the end of each magnitude row, in elements, with range [0, infinity)
111 * @param firstRow The first row to be handled, with range [0, height - 1]
112 * @param numberRows The number of rows to be handled, with range [1, height - firstRow]
113 */
114 static void magnitude2Channels8BitPerChannelSubset(const uint8_t* frame, uint16_t* magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, const unsigned int firstRow, const unsigned int numberRows);
115};
116
117template <typename T, typename TMagnitude>
118void FrameFilter::magnitude(const T* frame, TMagnitude* magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, Worker* worker)
119{
120 static_assert(sizeof(T) <= sizeof(TMagnitude), "Invalid data type!");
121
122 ocean_assert(frame != nullptr);
123 ocean_assert(magnitude != nullptr);
124 ocean_assert(channels >= 2u);
125 ocean_assert(width >= 1u && height >= 1u);
126
127 if (worker != nullptr)
128 {
129 worker->executeFunction(Worker::Function::createStatic(&magnitudeSubset<T, TMagnitude>, frame, magnitude, channels, width, height, framePaddingElements, magnitudePaddingElements, 0u, 0u), 0u, height);
130 }
131 else
132 {
133 magnitudeSubset<T, TMagnitude>(frame, magnitude, channels, width, height, framePaddingElements, magnitudePaddingElements, 0u, height);
134 }
135}
136
137template <typename T, T tNormalizationDenominator, bool tRoundedNormalization>
138inline T FrameFilter::normalizeValue(const T& value)
139{
140 static_assert(tNormalizationDenominator > T(0), "Invalid normalization!");
141
142 if constexpr (tNormalizationDenominator == T(1))
143 {
144 return value;
145 }
146
147 if constexpr (std::is_floating_point<T>::value)
148 {
149 return value / tNormalizationDenominator;
150 }
151 else
152 {
153 constexpr T tNormalizationDenominator_2 = tNormalizationDenominator / T(2);
154
155#ifdef OCEAN_DEBUG
156 ocean_assert((std::is_integral<T>::value));
157
158 if constexpr (tRoundedNormalization)
159 {
160 if constexpr (std::is_same<T, int32_t>::value)
161 {
162 ocean_assert(value >= NumericT<int32_t>::minValue() + tNormalizationDenominator_2);
163 ocean_assert(value <= NumericT<int32_t>::maxValue() - tNormalizationDenominator_2);
164 }
165
166 if constexpr (std::is_same<T, uint32_t>::value)
167 {
168 ocean_assert(value <= NumericT<uint32_t>::maxValue() - tNormalizationDenominator_2);
169 }
170
171 if constexpr (std::is_same<T, int64_t>::value)
172 {
173 ocean_assert(value >= NumericT<int64_t>::minValue() + tNormalizationDenominator_2);
174 ocean_assert(value <= NumericT<int64_t>::maxValue() - tNormalizationDenominator_2);
175 }
176
177 if constexpr (std::is_same<T, uint64_t>::value)
178 {
179 ocean_assert(value <= NumericT<uint64_t>::maxValue() - tNormalizationDenominator_2);
180 }
181 }
182#endif // OCEAN_DEBUG
183
184 if constexpr (tRoundedNormalization && std::is_signed<T>::value)
185 {
186 if (value >= T(0))
187 {
188 return (value + tNormalizationDenominator_2) / tNormalizationDenominator;
189 }
190 else
191 {
192 return (value - tNormalizationDenominator_2) / tNormalizationDenominator;
193 }
194 }
195 else
196 {
197 if constexpr (tRoundedNormalization)
198 {
199 return (value + tNormalizationDenominator_2) / tNormalizationDenominator;
200 }
201 else
202 {
203 return value / tNormalizationDenominator;
204 }
205 }
206 }
207}
208
209template <typename T, T tNormalizationDenominator, bool tRoundedNormalization>
210inline T FrameFilter::normalizeValueSlow(const T& value)
211{
212 if constexpr (std::is_integral<T>::value && tNormalizationDenominator != T(1) && tRoundedNormalization && sizeof(T) >= 4)
213 {
214 constexpr T tNormalizationDenominator_2 = (tNormalizationDenominator + 1) / T(2);
215
216 if constexpr (std::is_signed<T>::value)
217 {
218 if (value < T(0))
219 {
220 const T remainder = value % tNormalizationDenominator;
221
222 if (remainder <= -tNormalizationDenominator_2)
223 {
224 return value / tNormalizationDenominator - T(1);
225 }
226 else
227 {
228 return value / tNormalizationDenominator;
229 }
230 }
231
232 }
233
234 const T remainder = value % tNormalizationDenominator;
235
236 if (remainder >= tNormalizationDenominator_2)
237 {
238 return value / tNormalizationDenominator + T(1);
239 }
240 else
241 {
242 return value / tNormalizationDenominator;
243 }
244 }
245 else
246 {
247 return normalizeValue<T, tNormalizationDenominator, tRoundedNormalization>(value);
248 }
249}
250
251template <typename T, typename TMagnitude>
252void FrameFilter::magnitudeSubset(const T* frame, TMagnitude* magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
253{
254 static_assert(sizeof(T) <= sizeof(TMagnitude), "Invalid data type!");
255
256 ocean_assert(frame != nullptr);
257 ocean_assert(magnitude != nullptr);
258 ocean_assert(channels >= 2u);
259 ocean_assert(width >= 1u && height >= 1u);
260
261 ocean_assert_and_suppress_unused(firstRow + numberRows <= height, height);
262
263 if constexpr (std::is_same<T, uint8_t>::value && std::is_same<TMagnitude, uint16_t>::value)
264 {
265 if (channels == 2u)
266 {
267 magnitude2Channels8BitPerChannelSubset(frame, magnitude, channels, width, height, framePaddingElements, magnitudePaddingElements, firstRow, numberRows);
268 return;
269 }
270 }
271
272 using TSqrMagnitude = typename SquareValueTyper<TMagnitude>::Type;
273 using TIntermediateFloat = typename FloatTyper<TMagnitude>::Type;
274
275 const unsigned int frameStrideElements = width * channels + framePaddingElements;
276 const unsigned int magnitudeStrideElements = width + magnitudePaddingElements;
277
278 frame += firstRow * frameStrideElements;
279 magnitude += firstRow * magnitudeStrideElements;
280
281 for (unsigned int y = 0u; y < numberRows; ++y)
282 {
283 for (unsigned int x = 0u; x < width; ++x)
284 {
285 TSqrMagnitude sqrMagnitude = TSqrMagnitude(0);
286
287 for (unsigned int n = 0u; n < channels; ++n)
288 {
289 sqrMagnitude += TSqrMagnitude(frame[n]) * TSqrMagnitude(frame[n]);
290 }
291
292 const TIntermediateFloat floatMagnitude = NumericT<TIntermediateFloat>::sqrt(TIntermediateFloat(sqrMagnitude));
293
294 if constexpr (std::is_floating_point<TMagnitude>::value)
295 {
296 ocean_assert(NumericT<TMagnitude>::isInsideValueRange(floatMagnitude));
297 }
298 else
299 {
300 ocean_assert(TIntermediateFloat(NumericT<TMagnitude>::minValue()) <= floatMagnitude);
301 ocean_assert(floatMagnitude < TIntermediateFloat(NumericT<TMagnitude>::maxValue()));
302 }
303
304 *magnitude = TMagnitude(floatMagnitude);
305
306 frame += channels;
307 ++magnitude;
308 }
309
310 frame += framePaddingElements;
311 magnitude += magnitudePaddingElements;
312 }
313}
314
315}
316
317}
318
319#endif // META_OCEAN_CV_FRAME_FILTER_H
This class implements the base class for all filter.
Definition FrameFilter.h:29
static T normalizeValueSlow(const T &value)
Normalizes a given value with a template-based normalization factor.
Definition FrameFilter.h:210
static T normalizeValue(const T &value)
Normalizes a given value with a template-based normalization factor.
Definition FrameFilter.h:138
static void magnitude(const T *frame, TMagnitude *magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, Worker *worker=nullptr)
Determines the per-pixel magnitude of a frame.
Definition FrameFilter.h:118
static void magnitudeSubset(const T *frame, TMagnitude *magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Determines the per-pixel magnitude for a subset of a frame.
Definition FrameFilter.h:252
static void magnitude2Channels8BitPerChannelSubset(const uint8_t *frame, uint16_t *magnitude, const unsigned int channels, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int magnitudePaddingElements, const unsigned int firstRow, const unsigned int numberRows)
Determines the per-pixel magnitude for a subset of a frame.
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 provides basic numeric functionalities.
Definition Numeric.h:57
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1533
T Type
Definition of the data type for the square value.
Definition DataType.h:132
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
float Type
The 32 bit floating point data type for any data type T but 'double'.
Definition DataType.h:373