Ocean
Loading...
Searching...
No Matches
ZeroMeanSumSquareDifferencesBase.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_SUM_ZERO_MEAN_SQUARE_DIFFERENCES_BASE_H
9#define META_OCEAN_CV_SUM_ZERO_MEAN_SQUARE_DIFFERENCES_BASE_H
10
11#include "ocean/cv/CV.h"
13
14namespace Ocean
15{
16
17namespace CV
18{
19
20/**
21 * This class implements several zero-mean sum square differences functions based e.g., on template parameters.
22 * @ingroup cv
23 */
25{
26 public:
27
28 /**
29 * Returns the zero-mean sum of square differences between two square patches.
30 * @param image0 The first image in which the first patch is located, must be valid
31 * @param image1 The second image in which the second patch is located, must be valid
32 * @param width0 Width of the first frame in pixels, with range [tPatchSize, infinity)
33 * @param width1 Width of the second frame in pixels, with range [tPatchSize, infinity)
34 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, width0 - tPatchSize / 2 - 1]
35 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, height0 - tPatchSize / 2 - 1]
36 * @param centerX1 Horizontal center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize / 2, width1 - tPatchSize / 2 - 1]
37 * @param centerY1 Vertical center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize / 2, height1 - tPatchSize / 2 - 1]
38 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
39 * @param image1PaddingElements The number of padding elements at the end of each row of the second image, in elements, with range [0, infinity
40 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements
41 * @tparam tChannels Specifies the number of channels for the given frames, with range [1, infinity)
42 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
43 */
44 template <unsigned int tChannels, unsigned int tPatchSize>
45 static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannelTemplate(const uint8_t* const image0, const uint8_t* const image1, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements);
46
47 /**
48 * Returns the zero-mean sum of square differences between two square patches.
49 * @param patch0 The top-left corner of the first image patch, must be valid
50 * @param patch1 The top-left corner of the second image patch, must be valid
51 * @param patch0StrideElements The number of elements between two row starts in the first patch, in elements, with range [tPatchSize * tChannels, infinity)
52 * @param patch1StrideElements The number of elements between two row starts in the second patch, in elements, with range [tPatchSize * tChannels, infinity)
53 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements
54 * @tparam tChannels Specifies the number of channels for the given frames, with range [1, infinity)
55 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
56 */
57 template <unsigned int tChannels, unsigned int tPatchSize>
58 static uint32_t patch8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* patch1, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements);
59
60 /**
61 * Returns the zero-mean sum of square differences between a square image patch and a buffer.
62 * @param image0 The image in which the image patch is located, must be valid
63 * @param width0 Width of the first frame in pixels, with range [tPatchSize, infinity)
64 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, width0 - tPatchSize / 2 - 1]
65 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, height0 - tPatchSize / 2 - 1]
66 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
67 * @param buffer1 The memory buffer with `tChannels * tPatchSize * tPatchSize` elements, must be valid
68 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
69 * @tparam tChannels The number of channels for the given frames, with range [1, infinity)
70 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
71 */
72 template <unsigned int tChannels, unsigned int tPatchSize>
73 static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannelTemplate(const uint8_t* image0, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1);
74
75 /**
76 * Returns the zero-mean sum of square differences between a square image patch and a buffer.
77 * @param patch0 The top left start position of the image patch, must be valid
78 * @param buffer1 The memory buffer, must be valid
79 * @param patch0StrideElements The number of elements between two rows for the image patch, in elements, with range [tChannels, tPatchSize, infinity)
80 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
81 * @tparam tChannels The number of channels for the given frames, with range [1, infinity)
82 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
83 */
84 template <unsigned int tChannels, unsigned int tPatchSize>
85 static uint32_t patchBuffer8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* buffer1, const unsigned int patch0StrideElements);
86
87 /**
88 * Returns the zero-mean sum of square differences between two memory buffers.
89 * @param buffer0 The first memory buffer, must be valid
90 * @param buffer1 The second memory buffer, must be valid
91 * @return The resulting sum of square differences
92 * @tparam tChannels Specifies the number of channels for the given frames
93 * @tparam tPixels The number of pixels the buffer holds, in pixels, with range [1, infinity)
94 */
95 template <unsigned int tChannels, unsigned int tPixels>
96 static inline uint32_t buffer8BitPerChannelTemplate(const uint8_t* buffer0, const uint8_t* buffer1);
97
98 /**
99 * Returns the zero-mean sum of square differences between two square patches.
100 * @param image0 The first image in which the first patch is located, must be valid
101 * @param image1 The second image in which the second patch is located, must be valid
102 * @param width0 Width of the first frame in pixels, with range [patchSize, infinity)
103 * @param width1 Width of the second frame in pixels, with range [patchSize, infinity)
104 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
105 * @param centerX0 Horizontal center position of the (patchSize x patchSize) block in the first frame, with range [patchSize / 2, width0 - patchSize / 2 - 1]
106 * @param centerY0 Vertical center position of the (patchSize x patchSize) block in the first frame, with range [patchSize / 2, height0 - patchSize / 2 - 1]
107 * @param centerX1 Horizontal center position of the (patchSize x patchSize) block in the second frame, with range [patchSize / 2, width1 - patchSize / 2 - 1]
108 * @param centerY1 Vertical center position of the (patchSize x patchSize) block in the second frame, with range [patchSize / 2, height1 - patchSize / 2 - 1]
109 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
110 * @param image1PaddingElements The number of padding elements at the end of each row of the second image, in elements, with range [0, infinity
111 * @return The resulting sum of square differences for `patchSize * patchSize * channels` elements
112 * @tparam tChannels The number of frame channels, with range [1, infinity)
113 */
114 template <unsigned int tChannels>
115 static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannel(const uint8_t* const image0, const uint8_t* const image1, const unsigned int patchSize, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements);
116
117 /**
118 * Returns the zero-mean sum of square differences between two square patches.
119 * @param patch0 The top-left corner of the first image patch, must be valid
120 * @param patch1 The top-left corner of the second image patch, must be valid
121 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
122 * @param patch0StrideElements The number of elements between two row starts in the first patch, in elements, with range [patchSize * channels, infinity)
123 * @param patch1StrideElements The number of elements between two row starts in the second patch, in elements, with range [patchSize * channels, infinity)
124 * @return The resulting sum of square differences for `patchSize * patchSize * channels` elements
125 * @tparam tChannels The number of frame channels, with range [1, infinity)
126 */
127 template <unsigned int tChannels>
128 static uint32_t patch8BitPerChannel(const uint8_t* patch0, const uint8_t* patch1, const unsigned int patchSize, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements);
129
130 /**
131 * Returns the sum of square differences between a square image patch and a buffer.
132 * @param image0 The image in which the image patch is located, must be valid
133 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
134 * @param width0 Width of the first frame in pixels, with range [tPatchSize, infinity)
135 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, width0 - tPatchSize / 2 - 1]
136 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, height0 - tPatchSize / 2 - 1]
137 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
138 * @param buffer1 The memory buffer with `tChannels * tPatchSize * tPatchSize` elements, must be valid
139 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
140 * @tparam tChannels The number of frame channels, with range [1, infinity)
141 */
142 template <unsigned int tChannels>
143 static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannel(const uint8_t* image0, unsigned int patchSize, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1);
144
145 /**
146 * Returns the sum of square differences between a square image patch and a buffer.
147 * @param patch0 The top left start position of the image patch, must be valid
148 * @param buffer1 The memory buffer, must be valid
149 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
150 * @param patch0StrideElements The number of elements between two rows for the image patch, in elements, with range [tChannels, tPatchSize, infinity)
151 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
152 * @tparam tChannels The number of frame channels, with range [1, infinity)
153 */
154 template <unsigned int tChannels>
155 static uint32_t patchBuffer8BitPerChannel(const uint8_t* patch0, const uint8_t* buffer1, unsigned int patchSize, const unsigned int patch0StrideElements);
156
157 /**
158 * Returns the zero-mean sum of square differences between two memory buffers.
159 * @param buffer0 The first memory buffer, must be valid
160 * @param buffer1 The second memory buffer, must be valid
161 * @param pixels The number of pixels the buffer holds, in pixels, with range [1, infinity)
162 * @return The resulting sum of square differences
163 * @tparam tChannels Specifies the number of channels for the given frames
164 */
165 template <unsigned int tChannels>
166 static inline unsigned int buffer8BitPerChannel(const uint8_t* buffer0, const uint8_t* buffer1, const unsigned int pixels);
167
168 /**
169 * Returns the zero-mean sum of square differences between two patches within an image, patch pixels outside the image will be mirrored back into the image.
170 * @param image0 The image in which the first patch is located, must be valid
171 * @param image1 The image in which the second patch is located, must be valid
172 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
173 * @param width0 The width of the first image, in pixels, with range [tPatchSize, infinity)
174 * @param height0 The height of the first image, in pixels, with range [tPatchSize, infinity)
175 * @param width1 The width of the second image, in pixels, with range [tPatchSize, infinity)
176 * @param height1 The height of the second image, in pixels, with range [tPatchSize, infinity)
177 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize/2, width - tPatchSize/2 - 1]
178 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize/2, height - tPatchSize/2 - 1]
179 * @param centerX1 Horizontal center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize/2, width - tPatchSize/2 - 1]
180 * @param centerY1 Vertical center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize/2, height - tPatchSize/2 - 1]
181 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
182 * @param image1PaddingElements The number of padding elements at the end of each row of the second image, in elements, with range [0, infinity)
183 * @return The resulting sum of square differences, with range [0, infinity)
184 * @tparam tChannels Specifies the number of channels for the given frames
185 */
186 template <unsigned int tChannels>
187 static uint32_t patchMirroredBorder8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const unsigned int patchSize, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements);
188};
189
190template <unsigned int tChannels, unsigned int tPatchSize>
191inline uint32_t ZeroMeanSumSquareDifferencesBase::patch8BitPerChannelTemplate(const uint8_t* const image0, const uint8_t* const image1, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
192{
193 static_assert(tChannels >= 1u, "Invalid number of frame channels!");
194 static_assert(tPatchSize % 2u == 1u, "Invalid patch size!");
195
196 ocean_assert(image0 != nullptr && image1 != nullptr);
197
198 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
199
200 ocean_assert(centerX0 >= tPatchSize_2 && centerY0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2);
201 ocean_assert(centerX1 >= tPatchSize_2 && centerY1 >= tPatchSize_2 && centerX1 < width1 - tPatchSize_2);
202
203 ocean_assert(width0 >= tPatchSize);
204 ocean_assert(width1 >= tPatchSize);
205
206 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
207 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
208
209 return patch8BitPerChannelTemplate<tChannels, tPatchSize>(image0 + (centerY0 - tPatchSize_2) * image0StrideElements + (centerX0 - tPatchSize_2) * tChannels, image1 + (centerY1 - tPatchSize_2) * image1StrideElements + (centerX1 - tPatchSize_2) * tChannels, image0StrideElements, image1StrideElements);
210}
211
212template <unsigned int tChannels, unsigned int tPatchSize>
213uint32_t ZeroMeanSumSquareDifferencesBase::patch8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* patch1, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements)
214{
215 static_assert(tPatchSize % 2u == 1u, "Invalid image patch size, need an odd value!");
216 static_assert(tChannels > 0u, "Invalid number of frame channels!");
217
218 ocean_assert(patch0 != nullptr && patch1 != nullptr);
219
220 ocean_assert(patch0StrideElements >= tPatchSize * tChannels);
221 ocean_assert(patch1StrideElements >= tPatchSize * tChannels);
222
223 uint32_t sumMean0[tChannels] = {0u};
224 uint32_t sumMean1[tChannels] = {0u};
225
226 for (unsigned int y = 0u; y < tPatchSize; ++y)
227 {
228 for (unsigned int x = 0u; x < tPatchSize; ++x)
229 {
230 for (unsigned int c = 0u; c < tChannels; c++)
231 {
232 sumMean0[c] += patch0[c];
233 sumMean1[c] += patch1[c];
234 }
235
236 patch0 += tChannels;
237 patch1 += tChannels;
238 }
239
240 patch0 += patch0StrideElements - tPatchSize * tChannels;
241 patch1 += patch1StrideElements - tPatchSize * tChannels;
242 }
243
244 uint8_t mean0[tChannels];
245 uint8_t mean1[tChannels];
246
247 for (unsigned int n = 0u; n < tChannels; ++n)
248 {
249 mean0[n] = uint8_t((sumMean0[n] + (tPatchSize * tPatchSize / 2u)) / (tPatchSize * tPatchSize));
250 mean1[n] = uint8_t((sumMean1[n] + (tPatchSize * tPatchSize / 2u)) / (tPatchSize * tPatchSize));
251 }
252
253 patch0 -= patch0StrideElements * tPatchSize;
254 patch1 -= patch1StrideElements * tPatchSize;
255
256 uint32_t result = 0;
257 int16_t value = 0;
258
259 for (unsigned int y = 0u; y < tPatchSize; ++y)
260 {
261 for (unsigned int x = 0u; x < tPatchSize; ++x)
262 {
263 for (unsigned int c = 0u; c < tChannels; c++)
264 {
265 value = int16_t(patch0[c] - mean0[c]) - int16_t(patch1[c] - mean1[c]);
266 result += value * value;
267 }
268
269 patch0 += tChannels;
270 patch1 += tChannels;
271 }
272
273 patch0 += patch0StrideElements - tPatchSize * tChannels;
274 patch1 += patch1StrideElements - tPatchSize * tChannels;
275 }
276
277 return result;
278}
279
280template <unsigned int tChannels, unsigned int tPatchSize>
281OCEAN_FORCE_INLINE uint32_t ZeroMeanSumSquareDifferencesBase::patchBuffer8BitPerChannelTemplate(const uint8_t* image0, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1)
282{
283 static_assert(tChannels >= 1u, "Invalid number of frame channels!");
284 static_assert(tPatchSize % 2u == 1u, "Invalid patch size!");
285
286 ocean_assert(image0 != nullptr && buffer1 != nullptr);
287
288 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
289
290 ocean_assert(centerX0 >= tPatchSize_2 && centerY0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2);
291
292 ocean_assert(width0 >= tPatchSize);
293
294 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
295
296 return patchBuffer8BitPerChannelTemplate<tChannels, tPatchSize>(image0 + (centerY0 - tPatchSize_2) * image0StrideElements + (centerX0 - tPatchSize_2) * tChannels, buffer1, image0StrideElements);
297}
298
299template <unsigned int tChannels, unsigned int tPatchSize>
300uint32_t ZeroMeanSumSquareDifferencesBase::patchBuffer8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* buffer1, const unsigned int patch0StrideElements)
301{
302 return patch8BitPerChannelTemplate<tChannels, tPatchSize>(patch0, buffer1, patch0StrideElements, tChannels * tPatchSize);
303}
304
305template <unsigned int tChannels, unsigned int tPixels>
306inline uint32_t ZeroMeanSumSquareDifferencesBase::buffer8BitPerChannelTemplate(const uint8_t* buffer0, const uint8_t* buffer1)
307{
308 static_assert(tChannels != 0u, "Invalid number of frame channels!");
309 static_assert(tPixels != 0u, "Invalid image buffer size!");
310
311 ocean_assert(buffer0 != nullptr && buffer1 != nullptr);
312
313 uint32_t sumMean0[tChannels] = {0u};
314 uint32_t sumMean1[tChannels] = {0u};
315
316 for (unsigned int n = 0u; n < tPixels; ++n)
317 {
318 for (unsigned int c = 0u; c < tChannels; ++c)
319 {
320 sumMean0[c] += buffer0[c];
321 sumMean1[c] += buffer1[c];
322 }
323
324 buffer0 += tChannels;
325 buffer1 += tChannels;
326 }
327
328 uint8_t mean0[tChannels];
329 uint8_t mean1[tChannels];
330
331 for (unsigned int c = 0u; c < tChannels; ++c)
332 {
333 mean0[c] = uint8_t((sumMean0[c] + tPixels / 2u) / tPixels);
334 mean1[c] = uint8_t((sumMean1[c] + tPixels / 2u) / tPixels);
335 }
336
337 buffer0 -= tChannels * tPixels;
338 buffer1 -= tChannels * tPixels;
339
340 int16_t value;
341 uint32_t ssd = 0u;
342
343 for (unsigned int n = 0u; n < tPixels; ++n)
344 {
345 for (unsigned int c = 0u; c < tChannels; ++c)
346 {
347 value = int16_t(buffer0[c] - mean0[c]) - int16_t(buffer1[c] - mean1[c]);
348 ssd += uint32_t(value * value);
349 }
350
351 buffer0 += tChannels;
352 buffer1 += tChannels;
353 }
354
355 return ssd;
356}
357
358template <unsigned int tChannels>
359OCEAN_FORCE_INLINE uint32_t ZeroMeanSumSquareDifferencesBase::patch8BitPerChannel(const uint8_t* const image0, const uint8_t* const image1, const unsigned int patchSize, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
360{
361 static_assert(tChannels >= 1u, "Invalid channel number!");
362
363 ocean_assert(image0 != nullptr && image1 != nullptr);
364 ocean_assert(patchSize % 2u == 1u);
365
366 const unsigned int patchSize_2 = patchSize / 2u;
367
368 ocean_assert(centerX0 >= patchSize_2 && centerY0 >= patchSize_2 && centerX0 < width0 - patchSize_2);
369 ocean_assert(centerX1 >= patchSize_2 && centerY1 >= patchSize_2 && centerX1 < width1 - patchSize_2);
370
371 ocean_assert(width0 >= patchSize_2);
372 ocean_assert(width1 >= patchSize_2);
373
374 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
375 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
376
377 return patch8BitPerChannel<tChannels>(image0 + (centerY0 - patchSize_2) * image0StrideElements + (centerX0 - patchSize_2) * tChannels, image1 + (centerY1 - patchSize_2) * image1StrideElements + (centerX1 - patchSize_2) * tChannels, patchSize, image0StrideElements, image1StrideElements);
378}
379
380template <unsigned int tChannels>
381uint32_t ZeroMeanSumSquareDifferencesBase::patch8BitPerChannel(const uint8_t* patch0, const uint8_t* patch1, const unsigned int patchSize, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements)
382{
383 static_assert(tChannels >= 1u, "Invalid channel number!");
384
385 ocean_assert(patch0 != nullptr && patch1 != nullptr);
386 ocean_assert(patchSize % 2u == 1u);
387
388 ocean_assert(patch0StrideElements >= patchSize * tChannels);
389 ocean_assert(patch1StrideElements >= patchSize * tChannels);
390
391 uint32_t sumMean0[tChannels] = {0u};
392 uint32_t sumMean1[tChannels] = {0u};
393
394 for (unsigned int y = 0u; y < patchSize; ++y)
395 {
396 for (unsigned int x = 0u; x < patchSize; ++x)
397 {
398 for (unsigned int c = 0u; c < tChannels; c++)
399 {
400 sumMean0[c] += patch0[c];
401 sumMean1[c] += patch1[c];
402 }
403
404 patch0 += tChannels;
405 patch1 += tChannels;
406 }
407
408 patch0 += patch0StrideElements - patchSize * tChannels;
409 patch1 += patch1StrideElements - patchSize * tChannels;
410 }
411
412 uint8_t mean0[tChannels];
413 uint8_t mean1[tChannels];
414
415 for (unsigned int n = 0u; n < tChannels; ++n)
416 {
417 mean0[n] = uint8_t((sumMean0[n] + (patchSize * patchSize / 2u)) / (patchSize * patchSize));
418 mean1[n] = uint8_t((sumMean1[n] + (patchSize * patchSize / 2u)) / (patchSize * patchSize));
419 }
420
421 patch0 -= patch0StrideElements * patchSize;
422 patch1 -= patch1StrideElements * patchSize;
423
424 uint32_t result = 0;
425 int16_t value = 0;
426
427 for (unsigned int y = 0u; y < patchSize; ++y)
428 {
429 for (unsigned int x = 0u; x < patchSize; ++x)
430 {
431 for (unsigned int c = 0u; c < tChannels; c++)
432 {
433 value = int16_t(patch0[c] - mean0[c]) - int16_t(patch1[c] - mean1[c]);
434 result += value * value;
435 }
436
437 patch0 += tChannels;
438 patch1 += tChannels;
439 }
440
441 patch0 += patch0StrideElements - patchSize * tChannels;
442 patch1 += patch1StrideElements - patchSize * tChannels;
443 }
444
445 return result;
446}
447
448template <unsigned int tChannels>
449inline unsigned int ZeroMeanSumSquareDifferencesBase::buffer8BitPerChannel(const uint8_t* buffer0, const uint8_t* buffer1, const unsigned int pixels)
450{
451 static_assert(tChannels != 0u, "Invalid number of frame channels!");
452
453 ocean_assert(buffer0 != nullptr && buffer1 != nullptr);
454 ocean_assert(pixels >= 1u);
455
456 uint32_t sumMean0[tChannels] = {0u};
457 uint32_t sumMean1[tChannels] = {0u};
458
459 for (unsigned int n = 0u; n < pixels; ++n)
460 {
461 for (unsigned int c = 0u; c < tChannels; ++c)
462 {
463 sumMean0[c] += buffer0[c];
464 sumMean1[c] += buffer1[c];
465 }
466
467 buffer0 += tChannels;
468 buffer1 += tChannels;
469 }
470
471 uint8_t mean0[tChannels];
472 uint8_t mean1[tChannels];
473
474 for (unsigned int c = 0u; c < tChannels; ++c)
475 {
476 mean0[c] = uint8_t((sumMean0[c] + pixels / 2u) / pixels);
477 mean1[c] = uint8_t((sumMean1[c] + pixels / 2u) / pixels);
478 }
479
480 buffer0 -= tChannels * pixels;
481 buffer1 -= tChannels * pixels;
482
483 int16_t value;
484 uint32_t ssd = 0u;
485
486 for (unsigned int n = 0u; n < pixels; ++n)
487 {
488 for (unsigned int c = 0u; c < tChannels; ++c)
489 {
490 value = int16_t(buffer0[c] - mean0[c]) - int16_t(buffer1[c] - mean1[c]);
491 ssd += uint32_t(value * value);
492 }
493
494 buffer0 += tChannels;
495 buffer1 += tChannels;
496 }
497
498 return ssd;
499}
500
501template <unsigned int tChannels>
502OCEAN_FORCE_INLINE uint32_t ZeroMeanSumSquareDifferencesBase::patchBuffer8BitPerChannel(const uint8_t* image0, unsigned int patchSize, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1)
503{
504 static_assert(tChannels >= 1u, "Invalid channel number!");
505
506 ocean_assert(image0 != nullptr && buffer1 != nullptr);
507
508 ocean_assert(patchSize % 2u == 1u);
509
510 const unsigned int patchSize_2 = patchSize / 2u;
511
512 ocean_assert(centerX0 >= patchSize_2 && centerY0 >= patchSize_2 && centerX0 < width0 - patchSize_2);
513
514 ocean_assert(width0 >= patchSize);
515
516 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
517
518 return patchBuffer8BitPerChannel<tChannels>(image0 + (centerY0 - patchSize_2) * image0StrideElements + (centerX0 - patchSize_2) * tChannels, buffer1, patchSize, image0StrideElements);
519}
520
521template <unsigned int tChannels>
522inline uint32_t ZeroMeanSumSquareDifferencesBase::patchBuffer8BitPerChannel(const uint8_t* patch0, const uint8_t* buffer1, unsigned int patchSize, const unsigned int patch0StrideElements)
523{
524 return patch8BitPerChannel<tChannels>(patch0, buffer1, patchSize, patch0StrideElements, tChannels * patchSize);
525}
526
527template <unsigned int tChannels>
528uint32_t ZeroMeanSumSquareDifferencesBase::patchMirroredBorder8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const unsigned int patchSize, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
529{
530 static_assert(tChannels != 0u, "Invalid number of data channels!");
531
532 ocean_assert(image0 != nullptr && image1 != nullptr);
533 ocean_assert(patchSize % 2u == 1u);
534
535 const unsigned int patchSize_2 = patchSize / 2u;
536
537 ocean_assert(width0 >= patchSize_2);
538 ocean_assert(width1 >= patchSize_2);
539
540 ocean_assert(centerX0 < width0 && centerY0 < height0);
541 ocean_assert(centerX1 < width1 && centerY1 < height1);
542
543 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
544 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
545
546 const int left0 = int(centerX0 - patchSize_2);
547 const int top0 = int(centerY0 - patchSize_2);
548
549 const int left1 = int(centerX1 - patchSize_2);
550 const int top1 = int(centerY1 - patchSize_2);
551
552 const uint8_t* i0 = image0 + top0 * int(image0StrideElements) + left0 * int(tChannels);
553 const uint8_t* i1 = image1 + top1 * int(image1StrideElements) + left1 * int(tChannels);
554
555 unsigned int mean0[tChannels] = {0u};
556 unsigned int mean1[tChannels] = {0u};
557
558 unsigned int y0 = centerY0 - patchSize_2;
559 unsigned int y1 = centerY1 - patchSize_2;
560
561 const uint8_t* const i0End = i0 + patchSize * image0StrideElements;
562
563 while (i0 != i0End)
564 {
565 ocean_assert(i0 < i0End);
566
567 const uint8_t* c0 = i0 + CVUtilities::mirrorOffset(y0, height0) * int(image0StrideElements);
568 const uint8_t* c1 = i1 + CVUtilities::mirrorOffset(y1, height1) * int(image1StrideElements);
569
570 unsigned int x0 = centerX0 - patchSize_2;
571 unsigned int x1 = centerX1 - patchSize_2;
572
573 const uint8_t* const c0RowEnd = c0 + patchSize * tChannels;
574
575 while (c0 != c0RowEnd)
576 {
577 ocean_assert(c0 < c0RowEnd);
578
579 if (x0 < width0 && x1 < width1)
580 {
581 // both pixels lie inside the frame
582
583 for (unsigned int n = 0u; n < tChannels; ++n)
584 {
585 mean0[n] += c0[n];
586 mean1[n] += c1[n];
587 }
588
589 c0 += tChannels;
590 c1 += tChannels;
591 }
592 else if (x0 < width0)
593 {
594 // x0 lies inside the frame
595
596 ocean_assert(x1 >= width1);
597
598 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
599
600 for (unsigned int n = 0u; n < tChannels; ++n)
601 {
602 mean0[n] += c0[n];
603 mean1[n] += m1[n];
604 }
605
606 c0 += tChannels;
607 c1 += tChannels;
608 }
609 else if (x1 < width1)
610 {
611 // x1 lies inside the frame
612
613 ocean_assert(x0 >= width0);
614
615 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
616
617 for (unsigned int n = 0u; n < tChannels; ++n)
618 {
619 mean0[n] += m0[n];
620 mean1[n] += c1[n];
621 }
622
623 c0 += tChannels;
624 c1 += tChannels;
625 }
626 else
627 {
628 // neither x0 nor x1 lie inside the frame
629
630 ocean_assert(x0 >= width0 && x1 >= width1);
631
632 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
633 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
634
635 for (unsigned int n = 0u; n < tChannels; ++n)
636 {
637 mean0[n] += m0[n];
638 mean1[n] += m1[n];
639 }
640
641 c0 += tChannels;
642 c1 += tChannels;
643 }
644
645 ++x0;
646 ++x1;
647 }
648
649 i0 += image0StrideElements;
650 i1 += image1StrideElements;
651
652 ++y0;
653 ++y1;
654 }
655
656 for (unsigned int n = 0u; n < tChannels; ++n)
657 {
658 mean0[n] = (mean0[n] + (patchSize * patchSize / 2u)) / (patchSize * patchSize);
659 mean1[n] = (mean1[n] + (patchSize * patchSize / 2u)) / (patchSize * patchSize);
660 }
661
662 y0 = centerY0 - patchSize_2;
663 y1 = centerY1 - patchSize_2;
664
665 i0 = image0 + top0 * int(image0StrideElements) + left0 * int(tChannels);
666 i1 = image1 + top1 * int(image1StrideElements) + left1 * int(tChannels);
667
668 int32_t value;
669 uint32_t zmssd = 0u;
670
671 while (i0 != i0End)
672 {
673 ocean_assert(i0 < i0End);
674
675 const uint8_t* c0 = i0 + CVUtilities::mirrorOffset(y0, height0) * int(image0StrideElements);
676 const uint8_t* c1 = i1 + CVUtilities::mirrorOffset(y1, height1) * int(image1StrideElements);
677
678 unsigned int x0 = centerX0 - patchSize_2;
679 unsigned int x1 = centerX1 - patchSize_2;
680
681 const uint8_t* const c0RowEnd = c0 + patchSize * tChannels;
682
683 while (c0 != c0RowEnd)
684 {
685 ocean_assert(c0 < c0RowEnd);
686
687 if (x0 < width0 && x1 < width1)
688 {
689 // both pixels lie inside the frame
690
691 for (unsigned int n = 0u; n < tChannels; ++n)
692 {
693 value = (c0[n] - mean0[n]) - (c1[n] - mean1[n]);
694 zmssd += value * value;
695 }
696
697 c0 += tChannels;
698 c1 += tChannels;
699 }
700 else if (x0 < width0)
701 {
702 // x0 lies inside the frame
703
704 ocean_assert(x1 >= width1);
705
706 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
707
708 for (unsigned int n = 0u; n < tChannels; ++n)
709 {
710 value = (c0[n] - mean0[n]) - (m1[n] - mean1[n]);
711 zmssd += value * value;
712 }
713
714 c0 += tChannels;
715 c1 += tChannels;
716 }
717 else if (x1 < width1)
718 {
719 // x1 lies inside the frame
720
721 ocean_assert(x0 >= width0);
722
723 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
724
725 for (unsigned int n = 0u; n < tChannels; ++n)
726 {
727 value = (m0[n] - mean0[n]) - (c1[n] - mean1[n]);
728 zmssd += value * value;
729 }
730
731 c0 += tChannels;
732 c1 += tChannels;
733 }
734 else
735 {
736 // neither x0 nor x1 lie inside the frame
737
738 ocean_assert(x0 >= width0 && x1 >= width1);
739
740 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
741 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
742
743 for (unsigned int n = 0u; n < tChannels; ++n)
744 {
745 value = (m0[n] - mean0[n]) - (m1[n] - mean1[n]);
746 zmssd += value * value;
747 }
748
749 c0 += tChannels;
750 c1 += tChannels;
751 }
752
753 ++x0;
754 ++x1;
755 }
756
757 i0 += image0StrideElements;
758 i1 += image1StrideElements;
759
760 ++y0;
761 ++y1;
762 }
763
764 return zmssd;
765}
766
767}
768
769}
770
771#endif // META_OCEAN_CV_SUM_ZERO_MEAN_SQUARE_DIFFERENCES_BASE_H
static int mirrorOffset(const unsigned int index, const unsigned int elements)
Deprecated.
Definition CVUtilities.h:446
This class implements several zero-mean sum square differences functions based e.g....
Definition ZeroMeanSumSquareDifferencesBase.h:25
static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannel(const uint8_t *image0, unsigned int patchSize, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t *buffer1)
Returns the sum of square differences between a square image patch and a buffer.
Definition ZeroMeanSumSquareDifferencesBase.h:502
static uint32_t patchMirroredBorder8BitPerChannel(const uint8_t *image0, const uint8_t *image1, const unsigned int patchSize, const unsigned int width0, const unsigned int height0, const unsigned int width1, const unsigned int height1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
Returns the zero-mean sum of square differences between two patches within an image,...
Definition ZeroMeanSumSquareDifferencesBase.h:528
static uint32_t buffer8BitPerChannelTemplate(const uint8_t *buffer0, const uint8_t *buffer1)
Returns the zero-mean sum of square differences between two memory buffers.
Definition ZeroMeanSumSquareDifferencesBase.h:306
static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannel(const uint8_t *const image0, const uint8_t *const image1, const unsigned int patchSize, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
Returns the zero-mean sum of square differences between two square patches.
Definition ZeroMeanSumSquareDifferencesBase.h:359
static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannelTemplate(const uint8_t *image0, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t *buffer1)
Returns the zero-mean sum of square differences between a square image patch and a buffer.
Definition ZeroMeanSumSquareDifferencesBase.h:281
static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannelTemplate(const uint8_t *const image0, const uint8_t *const image1, const unsigned int width0, const unsigned int width1, const unsigned int centerX0, const unsigned int centerY0, const unsigned int centerX1, const unsigned int centerY1, const unsigned int image0PaddingElements, const unsigned int image1PaddingElements)
Returns the zero-mean sum of square differences between two square patches.
static unsigned int buffer8BitPerChannel(const uint8_t *buffer0, const uint8_t *buffer1, const unsigned int pixels)
Returns the zero-mean sum of square differences between two memory buffers.
Definition ZeroMeanSumSquareDifferencesBase.h:449
The namespace covering the entire Ocean framework.
Definition Accessor.h:15