Ocean
FrameNorm.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_NORM_H
9 #define META_OCEAN_CV_FRAME_NORM_H
10 
11 #include "ocean/cv/CV.h"
12 
13 #include "ocean/math/Numeric.h"
14 
15 namespace Ocean
16 {
17 
18 namespace CV
19 {
20 
21 /**
22  * This class implements functions allowing to determine norms of images e.g, a L2 norm.
23  * @ingroup cv
24  */
25 class OCEAN_CV_EXPORT FrameNorm
26 {
27  public:
28 
29  /**
30  * Determines the L2 norm (square root of summed squares) of given data.
31  * This function is actually a wrapper around normL2() - and applies the sqrt calculation in addition.
32  * @param data The data for which the norm value will be determined, must be valid
33  * @param size The size of the given data in elements, with range [1, infinity)
34  * @return The resulting L2 norm
35  * @tparam T Data type of each value, e.g., 'uint8_t' or 'float'
36  * @tparam TNorm The data type of the resulting norm (and the intermediate sum), e.g., 'uint32_t' or 'double'
37  * @see squaredNormL2().
38  */
39  template <typename T, typename TNorm>
40  static TNorm normL2(const T* data, const size_t size);
41 
42  /**
43  * Determines the L2 norm (square root of summed squares) of a given frame allowing to specify a padding to enable the application of e.g., sub-frames.
44  * This function is actually a wrapper around normL2() - and applies the sqrt calculation in addition.
45  * @param frame The data of the frame for which the norm value will be determined, must be valid
46  * @param width The width of the given frame in pixel, with range [1, infinity)
47  * @param height The height of the given frame in pixel, with range [1, infinity)
48  * @param framePaddingElements The number of padding elements at the end of each row, in elements, with range [0, infinity)
49  * @return The resulting L2 norm
50  * @tparam T Data type of each value, e.g., 'unsigned char' or 'float'
51  * @tparam TNorm The data type of the resulting norm (and the intermediate sum), e.g., 'unsigned int' or 'double'
52  * @see squaredNormL2().
53  */
54  template <typename T, typename TNorm>
55  static TNorm normL2(const T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements);
56 
57  /**
58  * Determines the squared L2 norm (summed squares) of given data.
59  * @param data The data for which the norm value will be determined, must be valid
60  * @param size The size of the given data in elements, with range [1, infinity)
61  * @return The resulting L2 norm
62  * @tparam T Data type of each value, e.g., 'uint8_t' or 'float'
63  * @tparam TNorm The data type of the resulting norm (and the intermediate sum), e.g., 'uint32_t' or 'double'
64  * @see normL2().
65  */
66  template <typename T, typename TNorm>
67  static TNorm squaredNormL2(const T* data, const size_t size);
68 
69  /**
70  * Determines the squared L2 norm (summed squares) of a given frame allowing to specify a padding to enable the application of e.g., sub-frames.
71  * @param frame The data of the frame for which the norm value will be determined, must be valid
72  * @param width The width of the given frame in pixel, with range [1, infinity)
73  * @param height The height of the given frame in pixel, with range [1, infinity)
74  * @param framePaddingElements The number of padding elements at the end of each row, in elements, with range [0, infinity)
75  * @return The resulting L2 norm
76  * @tparam T Data type of each value, e.g., 'unsigned char' or 'float'
77  * @tparam TNorm The data type of the resulting norm (and the intermediate sum), e.g., 'unsigned int' or 'double'
78  * @see normL2().
79  */
80  template <typename T, typename TNorm>
81  static TNorm squaredNormL2(const T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements);
82 };
83 
84 template <typename T, typename TNorm>
85 TNorm FrameNorm::normL2(const T* data, const size_t size)
86 {
87  ocean_assert(data != nullptr);
88  ocean_assert(size != 0);
89 
90  return NumericT<TNorm>::sqrt(squaredNormL2<T, TNorm>(data, size));
91 }
92 
93 template <typename T, typename TNorm>
94 TNorm FrameNorm::normL2(const T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements)
95 {
96  ocean_assert(frame != nullptr);
97  ocean_assert(width != 0u && height != 0u);
98 
99  return NumericT<TNorm>::sqrt(squaredNormL2<T, TNorm>(frame, width, height, framePaddingElements));
100 }
101 
102 template <typename T, typename TNorm>
103 TNorm FrameNorm::squaredNormL2(const T* data, const size_t size)
104 {
105  ocean_assert(data != nullptr);
106  ocean_assert(size != 0);
107 
108  // we will calculate four values in parallel
109  // thus, the compiler will have a direct hint to use SSE/NEON
110  // so that we can avoid to make individual implementations...
111 
112  TNorm result0 = TNorm(0);
113  TNorm result1 = TNorm(0);
114  TNorm result2 = TNorm(0);
115  TNorm result3 = TNorm(0);
116 
117  ocean_assert(NumericT<ptrdiff_t>::isInsideValueRange(size));
118 
119  ptrdiff_t n = 0;
120 
121  for (n = 0; n < ptrdiff_t(size) - 3; n += 4)
122  {
123  result0 += TNorm(data[n + 0] * data[n + 0]);
124  result1 += TNorm(data[n + 1] * data[n + 1]);
125  result2 += TNorm(data[n + 2] * data[n + 2]);
126  result3 += TNorm(data[n + 3] * data[n + 3]);
127  }
128 
129  TNorm result = result0 + result1 + result2 + result3;
130 
131  // now we have to handle the last (at most) three elements
132 
133  while (n < ptrdiff_t(size))
134  {
135  result += TNorm(data[n] * data[n]);
136 
137  ++n;
138  }
139 
140  return result;
141 }
142 
143 template <typename T, typename TNorm>
144 TNorm FrameNorm::squaredNormL2(const T* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements)
145 {
146  ocean_assert(frame != nullptr);
147  ocean_assert(width != 0u && height != 0u);
148 
149  if (framePaddingElements == 0u)
150  {
151  return squaredNormL2<T, TNorm>(frame, width * height);
152  }
153 
154  // we will calculate four values in parallel
155  // thus, the compiler will have a direct hint to use SSE/NEON
156  // so that we can avoid to make individual implementations...
157 
158  TNorm result0 = TNorm(0);
159  TNorm result1 = TNorm(0);
160  TNorm result2 = TNorm(0);
161  TNorm result3 = TNorm(0);
162 
163  ptrdiff_t x;
164 
165  for (unsigned int y = 0u; y < height; ++y)
166  {
167  for (x = 0; x < ptrdiff_t(width) - 3; x += 4)
168  {
169  result0 += TNorm(frame[x + 0] * frame[x + 0]);
170  result1 += TNorm(frame[x + 1] * frame[x + 1]);
171  result2 += TNorm(frame[x + 2] * frame[x + 2]);
172  result3 += TNorm(frame[x + 3] * frame[x + 3]);
173  }
174 
175  if (x + 0 < ptrdiff_t(width))
176  {
177  result0 += TNorm(frame[x + 0] * frame[x + 0]);
178  }
179 
180  if (x + 1 < ptrdiff_t(width))
181  {
182  result1 += TNorm(frame[x + 1] * frame[x + 1]);
183  }
184 
185  if (x + 2 < ptrdiff_t(width))
186  {
187  result2 += TNorm(frame[x + 2] * frame[x + 2]);
188  }
189 
190  frame += width + framePaddingElements;
191  }
192 
193  return result0 + result1 + result2 + result3;
194 }
195 
196 }
197 
198 }
199 
200 #endif // META_OCEAN_CV_FRAME_NORM_H
This class implements functions allowing to determine norms of images e.g, a L2 norm.
Definition: FrameNorm.h:26
static TNorm normL2(const T *data, const size_t size)
Determines the L2 norm (square root of summed squares) of given data.
Definition: FrameNorm.h:85
static TNorm squaredNormL2(const T *data, const size_t size)
Determines the squared L2 norm (summed squares) of given data.
Definition: FrameNorm.h:103
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
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15