Ocean
Loading...
Searching...
No Matches
SumSquareDifferencesBase.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_SQUARE_DIFFERENCES_BASE_H
9#define META_OCEAN_CV_SUM_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 sum square differences functions based e.g., on template parameters.
22 * @ingroup cv
23 */
24class OCEAN_CV_EXPORT SumSquareDifferencesBase
25{
26 public:
27
28 /**
29 * Returns the 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 first image, in elements, with range [0, infinity)
39 * @param image1PaddingElements The number of padding elements at the end of each 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 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)
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 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 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 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 sum of square differences between two individual buffers.
89 * @param buffer0 The first buffer, with `tBufferSize` elements, must be valid
90 * @param buffer1 The second buffer, with `tBufferSize` elements, must be valid
91 * @return The resulting sum of square differences, with range [0, infinity)
92 * @tparam tBufferSize The number of elements in each buffer, with range [1, infinity)
93 */
94 template <unsigned int tBufferSize>
95 static inline uint32_t buffer8BitPerChannelTemplate(const uint8_t* const buffer0, const uint8_t* const buffer1);
96
97 /**
98 * Returns the sum of square differences between two square image patches which can be partially outside of the images.
99 * @param image0 The image in which the first patch is located, must be valid
100 * @param image1 The image in which the second patch is located, must be valid
101 * @param width0 The width of the first image, in pixels, with range [tPatchSize/2 + 1, infinity)
102 * @param height0 The height of the first image, in pixels, with range [tPatchSize/2 + 1, infinity)
103 * @param width1 The width of the second image, in pixels, with range [tPatchSize/2 + 1, infinity)
104 * @param height1 The height of the second image, in pixels, with range [tPatchSize/2 + 1, infinity)
105 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [0, width0 - 1]
106 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [0, height0 - 1]
107 * @param centerX1 Horizontal center position of the (tPatchSize x tPatchSize) block in the second frame, with range [0, width1 - 1]
108 * @param centerY1 Vertical center position of the (tPatchSize x tPatchSize) block in the second frame, with range [0, height1 - 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 Pair holding the resulting ssd and the number of pixels which contributed to the ssd, an ssd of -1 if a patch0 pixel does not have a corresponding patch1 pixel
112 * @tparam tChannels The number of frame channels, with range [1, infinity)
113 * @tparam tPatchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
114 */
115 template <unsigned int tChannels, unsigned int tPatchSize>
116 static inline IndexPair32 patchAtBorder8BitPerChannelTemplate(const uint8_t* image0, const uint8_t* image1, 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);
117
118 /**
119 * Returns the sum of square differences between two patches within an image, patch pixels outside the image will be mirrored back into the image.
120 * @param image0 The image in which the first patch is located, must be valid
121 * @param image1 The image in which the second patch is located, must be valid
122 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
123 * @param width0 The width of the first image, in pixels, with range [tPatchSize, infinity)
124 * @param height0 The height of the first image, in pixels, with range [tPatchSize, infinity)
125 * @param width1 The width of the second image, in pixels, with range [tPatchSize, infinity)
126 * @param height1 The height of the second image, in pixels, with range [tPatchSize, infinity)
127 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize/2, width - tPatchSize/2 - 1]
128 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize/2, height - tPatchSize/2 - 1]
129 * @param centerX1 Horizontal center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize/2, width - tPatchSize/2 - 1]
130 * @param centerY1 Vertical center position of the (tPatchSize x tPatchSize) block in the second frame, with range [tPatchSize/2, height - tPatchSize/2 - 1]
131 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
132 * @param image1PaddingElements The number of padding elements at the end of each row of the second image, in elements, with range [0, infinity)
133 * @return The resulting sum of square differences, with range [0, infinity)
134 * @tparam tChannels Specifies the number of channels for the given frames
135 */
136 template <unsigned int tChannels>
137 static uint32_t patchMirroredBorder8BitPerChannelTemplate(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);
138
139 /**
140 * Returns the sum of square differences between two square patches.
141 * @param image0 The first image in which the first patch is located, must be valid
142 * @param image1 The second image in which the second patch is located, must be valid
143 * @param width0 Width of the first frame in pixels, with range [patchSize, infinity)
144 * @param width1 Width of the second frame in pixels, with range [patchSize, infinity)
145 * @param channels Specifies the number of channels for the given frames, with range [1, infinity)
146 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
147 * @param centerX0 Horizontal center position of the (patchSize x patchSize) block in the first frame, with range [patchSize / 2, width0 - patchSize / 2 - 1]
148 * @param centerY0 Vertical center position of the (patchSize x patchSize) block in the first frame, with range [patchSize / 2, height0 - patchSize / 2 - 1]
149 * @param centerX1 Horizontal center position of the (patchSize x patchSize) block in the second frame, with range [patchSize / 2, width1 - patchSize / 2 - 1]
150 * @param centerY1 Vertical center position of the (patchSize x patchSize) block in the second frame, with range [patchSize / 2, height1 - patchSize / 2 - 1]
151 * @param image0PaddingElements The number of padding elements at the end of each first image, in elements, with range [0, infinity)
152 * @param image1PaddingElements The number of padding elements at the end of each second image, in elements, with range [0, infinity)
153 * @return The resulting sum of square differences for `patchSize * patchSize * channels` elements
154 */
155 static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannel(const uint8_t* const image0, const uint8_t* const image1, const unsigned int channels, 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);
156
157 /**
158 * Returns the sum of square differences between two square patches.
159 * @param patch0 The top-left corner of the first image patch, must be valid
160 * @param patch1 The top-left corner of the second image patch, must be valid
161 * @param channels Specifies the number of channels for the given frames, with range [1, infinity)
162 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
163 * @param patch0StrideElements The number of elements between two row starts in the first patch, in elements, with range [patchSize * channels, infinity)
164 * @param patch1StrideElements The number of elements between two row starts in the second patch, in elements, with range [patchSize * channels, infinity)
165 * @return The resulting sum of square differences for `patchSize * patchSize * channels` elements
166 */
167 static uint32_t patch8BitPerChannel(const uint8_t* patch0, const uint8_t* patch1, const unsigned int channels, const unsigned int patchSize, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements);
168
169 /**
170 * Returns the sum of square differences between a square image patch and a buffer.
171 * @param image0 The image in which the image patch is located, must be valid
172 * @param channels The number of channels for the given frames, with range [1, infinity)
173 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
174 * @param width0 Width of the first frame in pixels, with range [tPatchSize, infinity)
175 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, width0 - tPatchSize / 2 - 1]
176 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [tPatchSize / 2, height0 - tPatchSize / 2 - 1]
177 * @param image0PaddingElements The number of padding elements at the end of each first image, in elements, with range [0, infinity)
178 * @param buffer1 The memory buffer with `tChannels * tPatchSize * tPatchSize` elements, must be valid
179 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
180 */
181 static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannel(const uint8_t* image0, unsigned int channels, unsigned int patchSize, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1);
182
183 /**
184 * Returns the sum of square differences between a square image patch and a buffer.
185 * @param patch0 The top left start position of the image patch, must be valid
186 * @param buffer1 The memory buffer, must be valid
187 * @param channels The number of channels for the given frames, with range [1, infinity)
188 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
189 * @param patch0StrideElements The number of elements between two rows for the image patch, in elements, with range [tChannels, tPatchSize, infinity)
190 * @return The resulting sum of square differences for tPatchSize * tPatchSize * tChannels elements, with range [0, infinity)
191 */
192 static inline uint32_t patchBuffer8BitPerChannel(const uint8_t* patch0, const uint8_t* buffer1, unsigned int channels, unsigned int patchSize, const unsigned int patch0StrideElements);
193
194 /**
195 * Returns the sum of square differences between two individual buffers.
196 * @param buffer0 The first buffer, with `size` elements, must be valid
197 * @param buffer1 The second buffer, with `size` elements, must be valid
198 * @param bufferSize The number of elements in each buffer, with range [1, infinity)
199 * @return The sum of square differences between both buffers, with range [0, infinity)
200 */
201 static uint32_t buffer8BitPerChannel(const uint8_t* const buffer0, const uint8_t* const buffer1, const unsigned int bufferSize);
202
203 /**
204 * Returns the sum of square differences between two square image patches which can be partially outside of the images.
205 * @param image0 The image in which the first patch is located, must be valid
206 * @param image1 The image in which the second patch is located, must be valid
207 * @param channels The number of frame channels, with range [1, infinity)
208 * @param patchSize The size of the square patch (the edge length) in pixel, with range [1, infinity), must be odd
209 * @param width0 The width of the first image, in pixels, with range [tPatchSize/2 + 1, infinity)
210 * @param height0 The height of the first image, in pixels, with range [tPatchSize/2 + 1, infinity)
211 * @param width1 The width of the second image, in pixels, with range [tPatchSize/2 + 1, infinity)
212 * @param height1 The height of the second image, in pixels, with range [tPatchSize/2 + 1, infinity)
213 * @param centerX0 Horizontal center position of the (tPatchSize x tPatchSize) block in the first frame, with range [0, width0 - 1]
214 * @param centerY0 Vertical center position of the (tPatchSize x tPatchSize) block in the first frame, with range [0, height0 - 1]
215 * @param centerX1 Horizontal center position of the (tPatchSize x tPatchSize) block in the second frame, with range [0, width1 - 1]
216 * @param centerY1 Vertical center position of the (tPatchSize x tPatchSize) block in the second frame, with range [0, height1 - 1]
217 * @param image0PaddingElements The number of padding elements at the end of each row of the first image, in elements, with range [0, infinity)
218 * @param image1PaddingElements The number of padding elements at the end of each row of the second image, in elements, with range [0, infinity)
219 * @return Pair holding the resulting ssd and the number of pixels which contributed to the ssd, an ssd of -1 if a patch0 pixel does not have a corresponding patch1 pixel
220 */
221 static IndexPair32 patchAtBorder8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const unsigned int channels, 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);
222};
223
224template <unsigned int tChannels, unsigned int tPatchSize>
225OCEAN_FORCE_INLINE uint32_t SumSquareDifferencesBase::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)
226{
227 static_assert(tPatchSize % 2u == 1u, "Invalid image patch size, need an odd value!");
228 static_assert(tChannels > 0u, "Invalid number of frame channels!");
229
230 ocean_assert(image0 != nullptr && image1 != nullptr);
231
232 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
233
234 ocean_assert(centerX0 >= tPatchSize_2 && centerY0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2);
235 ocean_assert(centerX1 >= tPatchSize_2 && centerY1 >= tPatchSize_2 && centerX1 < width1 - tPatchSize_2);
236
237 ocean_assert(width0 >= tPatchSize);
238 ocean_assert(width1 >= tPatchSize);
239
240 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
241 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
242
243 return patch8BitPerChannelTemplate<tChannels, tPatchSize>(image0 + (centerY0 - tPatchSize_2) * image0StrideElements + (centerX0 - tPatchSize_2) * tChannels, image1 + (centerY1 - tPatchSize_2) * image1StrideElements + (centerX1 - tPatchSize_2) * tChannels, image0StrideElements, image1StrideElements);
244}
245
246template <unsigned int tChannels, unsigned int tPatchSize>
247uint32_t SumSquareDifferencesBase::patch8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* patch1, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements)
248{
249 static_assert(tPatchSize != 0u, "Invalid image patch size, need an odd value!");
250 static_assert(tChannels != 0u, "Invalid number of frame channels!");
251
252 ocean_assert(patch0 != nullptr && patch1 != nullptr);
253
254 ocean_assert(patch0StrideElements >= tPatchSize * tChannels);
255 ocean_assert(patch1StrideElements >= tPatchSize * tChannels);
256
257 uint32_t result = 0u;
258 int16_t value = 0;
259
260 for (unsigned int y = 0u; y < tPatchSize; ++y)
261 {
262 for (unsigned int n = 0u; n < tPatchSize * tChannels; ++n)
263 {
264 value = int16_t(patch0[n]) - int16_t(patch1[n]);
265 result += value * value;
266 }
267
268 patch0 += patch0StrideElements;
269 patch1 += patch1StrideElements;
270 }
271
272 return result;
273}
274
275template <unsigned int tChannels, unsigned int tPatchSize>
276OCEAN_FORCE_INLINE uint32_t SumSquareDifferencesBase::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)
277{
278 static_assert(tChannels >= 1u, "Invalid number of frame channels!");
279 static_assert(tPatchSize % 2u == 1u, "Invalid patch size!");
280
281 ocean_assert(image0 != nullptr && buffer1 != nullptr);
282
283 constexpr unsigned int tPatchSize_2 = tPatchSize / 2u;
284
285 ocean_assert(centerX0 >= tPatchSize_2 && centerY0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2);
286
287 ocean_assert(width0 >= tPatchSize);
288
289 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
290
291 return patchBuffer8BitPerChannelTemplate<tChannels, tPatchSize>(image0 + (centerY0 - tPatchSize_2) * image0StrideElements + (centerX0 - tPatchSize_2) * tChannels, buffer1, image0StrideElements);
292}
293
294template <unsigned int tChannels, unsigned int tPatchSize>
295uint32_t SumSquareDifferencesBase::patchBuffer8BitPerChannelTemplate(const uint8_t* patch0, const uint8_t* buffer1, const unsigned int patch0StrideElements)
296{
297 return patch8BitPerChannelTemplate<tChannels, tPatchSize>(patch0, buffer1, patch0StrideElements, tChannels * tPatchSize);
298}
299
300template <unsigned int tBufferSize>
301inline uint32_t SumSquareDifferencesBase::buffer8BitPerChannelTemplate(const uint8_t* const buffer0, const uint8_t* const buffer1)
302{
303 static_assert(tBufferSize != 0u, "Invalid number of frame channels!");
304
305 ocean_assert(buffer0 != nullptr && buffer1 != nullptr);
306
307 int16_t difference;
308 uint32_t ssd = 0u;
309
310 for (unsigned int n = 0u; n < tBufferSize; ++n)
311 {
312 difference = int16_t(buffer0[n]) - int16_t(buffer1[n]);
313 ssd += uint32_t(difference * difference);
314 }
315
316 return ssd;
317}
318
319template <unsigned int tChannels, unsigned int tPatchSize>
320inline IndexPair32 SumSquareDifferencesBase::patchAtBorder8BitPerChannelTemplate(const uint8_t* image0, const uint8_t* image1, 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)
321{
322 static_assert(tChannels != 0u, "Invalid number of frame channels!");
323 static_assert(tPatchSize % 2u == 1u, "Invalid image patch size, must be odd!");
324
325 ocean_assert(image0 != nullptr && image1 != nullptr);
326
327 const unsigned int tPatchSize_2 = tPatchSize / 2u;
328
329 ocean_assert(width0 >= tPatchSize_2 + 1u && height0 >= tPatchSize_2 + 1u);
330 ocean_assert(width1 >= tPatchSize_2 + 1u && height1 >= tPatchSize_2 + 1u);
331
332 ocean_assert(centerX0 < width0 && centerY0 < height0);
333 ocean_assert(centerX1 < width1 && centerY1 < height1);
334
335 ocean_assert(centerX0 - tPatchSize_2 < width0 - (tPatchSize - 1u) == (centerX0 >= tPatchSize_2 && centerX0 < width0 - tPatchSize_2));
336 ocean_assert(centerY0 - tPatchSize_2 < height0 - (tPatchSize - 1u) == (centerY0 >= tPatchSize_2 && centerY0 < height0 - tPatchSize_2));
337 ocean_assert(centerX1 - tPatchSize_2 < width1 - (tPatchSize - 1u) == (centerX1 >= tPatchSize_2 && centerX1 < width1 - tPatchSize_2));
338 ocean_assert(centerY1 - tPatchSize_2 < height1 - (tPatchSize - 1u) == (centerY1 >= tPatchSize_2 && centerY1 < height1 - tPatchSize_2));
339
340 if (centerX0 - tPatchSize_2 < width0 - (tPatchSize - 1u) && centerY0 - tPatchSize_2 < height0 - (tPatchSize - 1u) && centerX1 - tPatchSize_2 < width1 - (tPatchSize - 1u) && centerY1 - tPatchSize_2 < height1 - (tPatchSize - 1u))
341 {
342 const uint32_t ssd = patch8BitPerChannelTemplate<tChannels, tPatchSize>(image0, image1, width0, width1, centerX0, centerY0, centerX1, centerY1, image0PaddingElements, image1PaddingElements);
343
344 return IndexPair32(ssd, tPatchSize * tPatchSize);
345 }
346
347 const unsigned int offsetLeft0 = min(centerX0, tPatchSize_2);
348 const unsigned int offsetTop0 = min(centerY0, tPatchSize_2);
349 const unsigned int offsetRight0 = min(width0 - centerX0 - 1u, tPatchSize_2);
350 const unsigned int offsetBottom0 = min(height0 - centerY0 - 1u, tPatchSize_2);
351
352 const unsigned int offsetLeft1 = min(centerX1, tPatchSize_2);
353 const unsigned int offsetTop1 = min(centerY1, tPatchSize_2);
354 const unsigned int offsetRight1 = min(width1 - centerX1 - 1u, tPatchSize_2);
355 const unsigned int offsetBottom1 = min(height1 - centerY1 - 1u, tPatchSize_2);
356
357 if (offsetLeft1 < offsetLeft0 || offsetRight1 < offsetRight0 || offsetTop1 < offsetTop0 || offsetBottom1 < offsetBottom0)
358 {
359 // at least one pixel in patch0 does not have a corresponding pixel in patch1 which lies inside image1s
360 return IndexPair32((unsigned int)(-1), 0u);
361 }
362
363 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
364 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
365
366 const unsigned int columns = offsetRight0 + 1u + offsetLeft0;
367 const unsigned int rows = offsetBottom0 + 1u + offsetTop0;
368
369 const uint8_t* patch0 = image0 + (centerY0 - offsetTop0) * image0StrideElements + (centerX0 - offsetLeft0) * tChannels;
370 const uint8_t* patch1 = image1 + (centerY1 - offsetTop0) * image1StrideElements + (centerX1 - offsetLeft0) * tChannels; // usage of offsetTop0 and offsetLeft0 is intended
371
372 unsigned int ssd = 0u;
373
374 for (unsigned int y = 0u; y < rows; ++y)
375 {
376 for (unsigned int x = 0u; x < columns; ++x)
377 {
378 for (unsigned int n = 0u; n < tChannels; ++n)
379 {
380 ssd += sqrDistance(patch0[x * tChannels + n], patch1[x * tChannels + n]);
381 }
382 }
383
384 patch0 += image0StrideElements;
385 patch1 += image1StrideElements;
386 }
387
388 return IndexPair32(ssd, rows * columns);
389}
390
391template <unsigned int tChannels>
392uint32_t SumSquareDifferencesBase::patchMirroredBorder8BitPerChannelTemplate(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)
393{
394 static_assert(tChannels != 0u, "Invalid number of data channels!");
395
396 ocean_assert(image0 != nullptr && image1 != nullptr);
397 ocean_assert(patchSize % 2u == 1u);
398
399 const unsigned int patchSize_2 = patchSize / 2u;
400
401 ocean_assert(width0 >= patchSize_2);
402 ocean_assert(width1 >= patchSize_2);
403
404 ocean_assert(centerX0 < width0 && centerY0 < height0);
405 ocean_assert(centerX1 < width1 && centerY1 < height1);
406
407 const unsigned int image0StrideElements = width0 * tChannels + image0PaddingElements;
408 const unsigned int image1StrideElements = width1 * tChannels + image1PaddingElements;
409
410 const int left0 = int(centerX0 - patchSize_2);
411 const int top0 = int(centerY0 - patchSize_2);
412
413 const int left1 = int(centerX1 - patchSize_2);
414 const int top1 = int(centerY1 - patchSize_2);
415
416 const uint8_t* i0 = image0 + top0 * int(image0StrideElements) + int(left0) * int(tChannels);
417 const uint8_t* i1 = image1 + top1 * int(image1StrideElements) + int(left1) * int(tChannels);
418
419 int32_t value;
420 uint32_t ssd = 0u;
421
422 unsigned int y0 = centerY0 - patchSize_2;
423 unsigned int y1 = centerY1 - patchSize_2;
424
425 const uint8_t* const i0End = i0 + patchSize * image0StrideElements;
426
427 while (i0 != i0End)
428 {
429 ocean_assert(i0 < i0End);
430
431 const uint8_t* c0 = i0 + CVUtilities::mirrorOffset(y0, height0) * int(image0StrideElements);
432 const uint8_t* c1 = i1 + CVUtilities::mirrorOffset(y1, height1) * int(image1StrideElements);
433
434 unsigned int x0 = centerX0 - patchSize_2;
435 unsigned int x1 = centerX1 - patchSize_2;
436
437 const uint8_t* const c0RowEnd = c0 + patchSize * tChannels;
438
439 while (c0 != c0RowEnd)
440 {
441 ocean_assert(c0 < c0RowEnd);
442
443 if (x0 < width0 && x1 < width1)
444 {
445 // both pixels lie inside the frame
446
447 for (unsigned int n = 0u; n < tChannels; ++n)
448 {
449 value = *c0++ - *c1++;
450 ssd += value * value;
451 }
452 }
453 else if (x0 < width0)
454 {
455 // x0 lies inside the frame
456
457 ocean_assert(x1 >= width1);
458
459 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
460
461 for (unsigned int n = 0u; n < tChannels; ++n)
462 {
463 value = *c0++ - *m1++;
464 ssd += value * value;
465 }
466
467 c1 += tChannels;
468 }
469 else if (x1 < width1)
470 {
471 // x1 lies inside the frame
472
473 ocean_assert(x0 >= width0);
474
475 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
476
477 for (unsigned int n = 0u; n < tChannels; ++n)
478 {
479 value = *m0++ - *c1++;
480 ssd += value * value;
481 }
482
483 c0 += tChannels;
484 }
485 else
486 {
487 // neither x0 nor x1 lie inside the frame
488
489 ocean_assert(x0 >= width0 && x1 >= width1);
490
491 const uint8_t* m1 = c1 + CVUtilities::mirrorOffset(x1, width1) * int(tChannels);
492 const uint8_t* m0 = c0 + CVUtilities::mirrorOffset(x0, width0) * int(tChannels);
493
494 for (unsigned int n = 0u; n < tChannels; ++n)
495 {
496 value = *m0++ - *m1++;
497 ssd += value * value;
498 }
499
500 c0 += tChannels;
501 c1 += tChannels;
502 }
503
504 ++x0;
505 ++x1;
506 }
507
508 i0 += image0StrideElements;
509 i1 += image1StrideElements;
510
511 ++y0;
512 ++y1;
513 }
514
515 return ssd;
516}
517
518OCEAN_FORCE_INLINE uint32_t SumSquareDifferencesBase::patch8BitPerChannel(const uint8_t* image0, const uint8_t* image1, const unsigned int channels, 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)
519{
520 ocean_assert(image0 != nullptr && image1 != nullptr);
521
522 ocean_assert(patchSize % 2u == 1u);
523 ocean_assert(channels > 0u);
524
525 const unsigned int patchSize_2 = patchSize / 2u;
526
527 ocean_assert(centerX0 >= patchSize_2 && centerY0 >= patchSize_2 && centerX0 < width0 - patchSize_2);
528 ocean_assert(centerX1 >= patchSize_2 && centerY1 >= patchSize_2 && centerX1 < width1 - patchSize_2);
529
530 ocean_assert(width0 >= patchSize_2);
531 ocean_assert(width1 >= patchSize_2);
532
533 const unsigned int image0StrideElements = width0 * channels + image0PaddingElements;
534 const unsigned int image1StrideElements = width1 * channels + image1PaddingElements;
535
536 return patch8BitPerChannel(image0 + (centerY0 - patchSize_2) * image0StrideElements + (centerX0 - patchSize_2) * channels, image1 + (centerY1 - patchSize_2) * image1StrideElements + (centerX1 - patchSize_2) * channels, channels, patchSize, image0StrideElements, image1StrideElements);
537}
538
539OCEAN_FORCE_INLINE uint32_t SumSquareDifferencesBase::patchBuffer8BitPerChannel(const uint8_t* image0, unsigned int channels, unsigned int patchSize, const unsigned int width0, const unsigned int centerX0, const unsigned int centerY0, const unsigned int image0PaddingElements, const uint8_t* buffer1)
540{
541 ocean_assert(image0 != nullptr && buffer1 != nullptr);
542
543 ocean_assert(channels >= 1u);
544 ocean_assert(patchSize % 2u == 1u);
545
546 const unsigned int patchSize_2 = patchSize / 2u;
547
548 ocean_assert(centerX0 >= patchSize_2 && centerY0 >= patchSize_2 && centerX0 < width0 - patchSize_2);
549
550 ocean_assert(width0 >= patchSize);
551
552 const unsigned int image0StrideElements = width0 * channels + image0PaddingElements;
553
554 return patchBuffer8BitPerChannel(image0 + (centerY0 - patchSize_2) * image0StrideElements + (centerX0 - patchSize_2) * channels, buffer1, channels, patchSize, image0StrideElements);
555}
556
557inline uint32_t SumSquareDifferencesBase::patchBuffer8BitPerChannel(const uint8_t* patch0, const uint8_t* buffer1, unsigned int channels, unsigned int patchSize, const unsigned int patch0StrideElements)
558{
559 return patch8BitPerChannel(patch0, buffer1, channels, patchSize, patch0StrideElements, channels * patchSize);
560}
561
562}
563
564}
565
566#endif // META_OCEAN_CV_SUM_SQUARE_DIFFERENCES_BASE_H
static int mirrorOffset(const unsigned int index, const unsigned int elements)
Deprecated.
Definition CVUtilities.h:446
This class implements several sum square differences functions based e.g., on template parameters.
Definition SumSquareDifferencesBase.h:25
static OCEAN_FORCE_INLINE uint32_t patch8BitPerChannel(const uint8_t *const image0, const uint8_t *const image1, const unsigned int channels, 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 sum of square differences between two square patches.
Definition SumSquareDifferencesBase.h:518
static IndexPair32 patchAtBorder8BitPerChannelTemplate(const uint8_t *image0, const uint8_t *image1, 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 sum of square differences between two square image patches which can be partially outside...
Definition SumSquareDifferencesBase.h:320
static uint32_t patch8BitPerChannel(const uint8_t *patch0, const uint8_t *patch1, const unsigned int channels, const unsigned int patchSize, const unsigned int patch0StrideElements, const unsigned int patch1StrideElements)
Returns the sum of square differences between two square patches.
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 sum of square differences between a square image patch and a buffer.
Definition SumSquareDifferencesBase.h:276
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 sum of square differences between two square patches.
Definition SumSquareDifferencesBase.h:225
static OCEAN_FORCE_INLINE uint32_t patchBuffer8BitPerChannel(const uint8_t *image0, unsigned int channels, 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 SumSquareDifferencesBase.h:539
static uint32_t buffer8BitPerChannel(const uint8_t *const buffer0, const uint8_t *const buffer1, const unsigned int bufferSize)
Returns the sum of square differences between two individual buffers.
static IndexPair32 patchAtBorder8BitPerChannel(const uint8_t *image0, const uint8_t *image1, const unsigned int channels, 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 sum of square differences between two square image patches which can be partially outside...
static uint32_t buffer8BitPerChannelTemplate(const uint8_t *const buffer0, const uint8_t *const buffer1)
Returns the sum of square differences between two individual buffers.
Definition SumSquareDifferencesBase.h:301
static uint32_t patchMirroredBorder8BitPerChannelTemplate(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 sum of square differences between two patches within an image, patch pixels outside the i...
Definition SumSquareDifferencesBase.h:392
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1089
std::pair< Index32, Index32 > IndexPair32
Definition of a pair holding 32 bit indices.
Definition Base.h:138
The namespace covering the entire Ocean framework.
Definition Accessor.h:15