Ocean
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"
12 #include "ocean/cv/CVUtilities.h"
13 
14 namespace Ocean
15 {
16 
17 namespace CV
18 {
19 
20 /**
21  * This class implements several sum square differences functions based e.g., on template parameters.
22  * @ingroup cv
23  */
24 class 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 
224 template <unsigned int tChannels, unsigned int tPatchSize>
225 OCEAN_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 
246 template <unsigned int tChannels, unsigned int tPatchSize>
247 uint32_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 
275 template <unsigned int tChannels, unsigned int tPatchSize>
276 OCEAN_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 
294 template <unsigned int tChannels, unsigned int tPatchSize>
295 uint32_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 
300 template <unsigned int tBufferSize>
301 inline 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 
319 template <unsigned int tChannels, unsigned int tPatchSize>
320 inline 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 
391 template <unsigned int tChannels>
392 uint32_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 
518 OCEAN_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 
539 OCEAN_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 
557 inline 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