Ocean
Loading...
Searching...
No Matches
FrameVariance.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_VARIANCE_H
9#define META_OCEAN_CV_FRAME_VARIANCE_H
10
11#include "ocean/cv/CV.h"
12
13#include "ocean/math/Numeric.h"
14
15namespace Ocean
16{
17
18namespace CV
19{
20
21
22/**
23 * This class implements functions to determine the frame variance.
24 * @ingroup cv
25 */
26class OCEAN_CV_EXPORT FrameVariance
27{
28 public:
29
30 /**
31 * This functions determines the frame deviation of a 1 channel 8 bit frame.
32 * @param frame Original frame to determine the variance for
33 * @param integral Bordered integral frame of the original frame with border size equal have of the specified window size, the border must be mirrored
34 * @param deviation Resulting deviation frame
35 * @param width The width of the original frame
36 * @param height The height of the original frame
37 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
38 * @param deviationPaddingElements The number of padding elements at the end of each deviation row, in elements, with range [0, infinity)
39 * @param window Size of the window must be odd, with range [1, infinity)
40 * @return True, if succeeded
41 */
42 template <typename T, typename TIntegral>
43 static bool deviation1Channel8Bit(const T* frame, const TIntegral* integral, uint8_t* deviation, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int deviationPaddingElements, const unsigned int window);
44
45 /**
46 * This functions determines the deviation within a 1-channel 8 bit frame.<br>
47 * The function uses an integral image for the calculation of the deviation.
48 * @param frame The frame for which the deviation will be determined, must be valid
49 * @param deviation Resulting deviation frame
50 * @param width The width of the given frame, in pixel, with range [1, infinity)
51 * @param height The height of the given frame, in pixel, with range [1, infinity)
52 * @param framePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
53 * @param deviationPaddingElements The number of padding elements at the end of each deviation row, in elements, with range [0, infinity)
54 * @param window Size of the window must be odd, with range [1, min(width, height) * 2]
55 * @return True, if succeeded
56 * @tparam T The data type of the frame elements, either 'int8_t' or 'uint8_t'
57 */
58 template <typename T>
59 static bool deviation1Channel8Bit(const T* frame, uint8_t* deviation, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int deviationPaddingElements, const unsigned int window);
60
61 /**
62 * Compute the per-channel mean, variance, and standard deviation over an image
63 *
64 * The basic outline of the computation is this (this example assumes no multi-channel and no stride but the actual implementation supports both, of course):
65 * @code
66 * T0 imagePixels[pixelCount] = { ... };
67 * T1 sum = 0;
68 * T1 squareSum = 0;
69 * for (i = 0; i < pixelCount; ++i)
70 * {
71 * sum[i] += T1(imagePixels[i]);
72 * squareSum[i] += T1(T2(imagePixel[i]) * T2(imagePixels[i]))
73 * }
74 * double mean = (double)sum / (double)pixelCount
75 * double variance = ((double)squareSum / pixelCount) - (mean * mean);
76 * double stddev = std::sqrt(variance)
77 *
78 * // Type `T0` is the type of the pixel elements, `T1` is used for the summations and type `T2` is used for multiplications.
79 * // This allows for a optimal control over how to compute and with what precision.
80 * // Example configurations are:
81 * // - `T0`=float, `T1`=float, `T2`=double
82 * // - `T0`=unsigned char, `T1`=unsigned long long, `T2`=unsigned short
83 * @endcode
84 * @note The most related OpenCV function is cv::meanStdDev()
85 * @param frame The input frame; mustn't be empty and must be a 1-channel image
86 * @param width The width of the input image, range: [1, infinity)
87 * @param height The height of the input image, range: [1, infinity)
88 * @param framePaddingElements Optional number of padding elements at the end of each source row, in elements, with range [0, infinity)
89 * @param mean Array for the resulting per-channel mean values, will be ignored if set to `nullptr` otherwise it must have `channels` elements
90 * @param variance Array for the resulting per-channel variance, will be ignored if set to `nullptr` otherwise it must have `channels` elements
91 * @param standardDeviation Array for the resulting per-channel standard deviations, will be ignored if set to `nullptr` otherwise it must have `channels` elements
92 * @tparam TElementType Type of the elements of the pixels of the input image
93 * @tparam TSummationType Type used for the internal computation of the pixel sums (should be at least as large as `TElementType`), cf. function description for details
94 * @tparam TMultiplicationType Type used to compute the square values of pixels (allows control over integer vs. floating point multiplication), cf. function description for details
95 * @tparam tChannels Number of channels of the input image, range: [1, infinity)
96 */
97 template <typename TElementType, typename TSummationType, typename TMultiplicationType, unsigned int tChannels>
98 static void imageStatistics(const TElementType* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, double* mean = nullptr, double* variance = nullptr, double* standardDeviation = nullptr);
99};
100
101template <typename TElementType, typename TSummationType, typename TMultiplicationType, unsigned int tChannels>
102void FrameVariance::imageStatistics(const TElementType* frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, double* mean, double* variance, double* standardDeviation)
103{
104 static_assert(tChannels != 0u, "Number of channels must be in the range [1, infinity)");
105 ocean_assert(frame != nullptr);
106 ocean_assert(width != 0u && height != 0u);
107
108 const unsigned int pixelCount = width * height;
109 const unsigned int elementsCount = (width * tChannels + framePaddingElements) * height;
110
111 const TElementType* const frameEnd = frame + elementsCount;
112
113 TSummationType sum[tChannels];
114 TSummationType squareSum[tChannels];
115 memset(sum, 0, tChannels * sizeof(TSummationType));
116 memset(squareSum, 0, tChannels * sizeof(TSummationType));
117
118 if (framePaddingElements == 0u)
119 {
120 for (unsigned int i = 0u; i < pixelCount; ++i)
121 {
122 for (unsigned int c = 0u; c < tChannels; ++c)
123 {
124 ocean_assert_and_suppress_unused(frame < frameEnd, frameEnd);
125
126 sum[c] += TSummationType(*frame);
127
128 ocean_assert(std::is_integral<TSummationType>::value == false || (squareSum[c] <= NumericT<TSummationType>::maxValue() - TSummationType(TMultiplicationType(*frame) * TMultiplicationType(*frame)) && "Integer overflow; TSummationType must be a wider type, cf. NextLargerTyper<TSummationType>::Type"));
129
130 squareSum[c] += TSummationType(TMultiplicationType(*frame) * TMultiplicationType(*frame));
131
132 frame++;
133 }
134 }
135 }
136 else
137 {
138 for (unsigned int y = 0u; y < height; ++y)
139 {
140 for (unsigned int x = 0u; x < width; ++x)
141 {
142 for (unsigned int c = 0u; c < tChannels; ++c)
143 {
144 ocean_assert(frame < frameEnd);
145
146 sum[c] += TSummationType(*frame);
147
148 ocean_assert(std::is_integral<TSummationType>::value == false || (squareSum[c] <= NumericT<TSummationType>::maxValue() - TSummationType(TMultiplicationType(*frame) * TMultiplicationType(*frame)) && "Integer overflow; TSummationType must be a wider type, cf. NextLargerTyper<TSummationType>::Type"));
149
150 squareSum[c] += TSummationType(TMultiplicationType(*frame) * TMultiplicationType(*frame));
151
152 frame++;
153 }
154 }
155
156 frame += framePaddingElements;
157 }
158 }
159
160 double localMean[tChannels];
161 double localVariance[tChannels];
162
163 ocean_assert(pixelCount != 0u);
164 const double normalizer = 1.0 / double(pixelCount);
165
166 for (unsigned int c = 0u; c < tChannels; ++c)
167 {
168 localMean[c] = double(sum[c]) * normalizer;
169
170 // var = sum((I_i - mean)^2) / N, i = 1...N
171 // = (sum(I_i^2)) / N) - (2 * sum(I_i) * mean / N) + mean^2
172 // = (sum(I_i^2)) / N) - (2 * mean * mean) + mean^2
173 // = (sum(I_i^2)) / N) - mean^2
174 localVariance[c] = std::max(0.0, (double(squareSum[c]) * normalizer) - (localMean[c] * localMean[c]));
175 }
176
177 if (mean)
178 {
179 for (unsigned int c = 0u; c < tChannels; ++c)
180 {
181 mean[c] = localMean[c];
182 }
183 }
184
185 if (variance)
186 {
187 for (unsigned int c = 0u; c < tChannels; ++c)
188 {
189 variance[c] = localVariance[c];
190 }
191 }
192
193 if (standardDeviation)
194 {
195 for (unsigned int c = 0u; c < tChannels; ++c)
196 {
197 ocean_assert(localVariance[c] >= 0.0);
198 standardDeviation[c] = NumericD::sqrt(localVariance[c]);
199 }
200 }
201}
202
203} // namespace CV
204
205} // namespace Ocean
206
207#endif // META_OCEAN_CV_FRAME_VARIANCE_H
This class implements functions to determine the frame variance.
Definition FrameVariance.h:27
static void imageStatistics(const TElementType *frame, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, double *mean=nullptr, double *variance=nullptr, double *standardDeviation=nullptr)
Compute the per-channel mean, variance, and standard deviation over an image.
Definition FrameVariance.h:102
static bool deviation1Channel8Bit(const T *frame, uint8_t *deviation, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int deviationPaddingElements, const unsigned int window)
This functions determines the deviation within a 1-channel 8 bit frame.
static bool deviation1Channel8Bit(const T *frame, const TIntegral *integral, uint8_t *deviation, const unsigned int width, const unsigned int height, const unsigned int framePaddingElements, const unsigned int deviationPaddingElements, const unsigned int window)
This functions determines the frame deviation of a 1 channel 8 bit frame.
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