Ocean
Loading...
Searching...
No Matches
LegacyPointDetector.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_CALIBRATION_LEGACY_POINT_DETECTOR_H
9#define META_OCEAN_CV_CALIBRATION_LEGACY_POINT_DETECTOR_H
10
13
14#include "ocean/base/Frame.h"
16#include "ocean/base/Worker.h"
17
20
22
23#include "ocean/math/Variance.h"
24
25namespace Ocean
26{
27
28namespace CV
29{
30
31namespace Calibration
32{
33
34/**
35 * This class implements a point detector for marker points.
36 * @ingroup cvcalibration
37 */
38class OCEAN_CV_CALIBRATION_EXPORT LegacyPointDetector
39{
41
42 public:
43
44 /**
45 * Definition of a pair combining an index with a distance.
46 */
47 using IndexDistancePair = std::pair<Index32, Scalar>;
48
49 /**
50 * Definition of a static vector holding IndexDistancePair objects.
51 * @tparam tNumber The number of elements the vector can hold at most, with range [1, infinity)
52 */
53 template <unsigned int tNumber>
55
56 protected:
57
58 /**
59 * This class implements a pattern for fast point detection.
60 * The pattern is defined by a radius and an inner radius defining a ring area around the center pixel.<br>
61 * Points can be detected by comparing the color intensity of the center pixel with the color intensities of the surrounding pixels in the ring area.
62 */
64 {
65 public:
66
67 /**
68 * Creates a new point pattern with same properties as a given point pattern but with different frame stride.
69 * @param pointPattern The point pattern to be copied, must be valid
70 * @param frameStrideElements The stride of the frame in which the point pattern will be used, in elements, with range [frame.width(), infinity)
71 */
72 PointPattern(const PointPattern& pointPattern, const unsigned int frameStrideElements);
73
74 /**
75 * Creates a new point pattern.
76 * @param radius The radius of the point pattern, with range [1, infinity)
77 * @param innerRadius The innerRadius defining a circular area around the center pixel where pixel data is excluded from use, with range [0, radius - 1]
78 * @param frameStrideElements The stride of the frame in which the point pattern is used, in elements, with range [frame
79 * @param useCircle True, if the outer shape of the point pattern is a circle; False, if the outer shape is a rectangle
80 */
81 PointPattern(const unsigned int radius, const unsigned int innerRadius, const unsigned int frameStrideElements, const bool useCircle = true);
82
83 /**
84 * Returns the radius of the point this pattern is able to detect.
85 * @return The point's radius, in pixel, with range [1, infinity)
86 */
87 inline unsigned int radius() const;
88
89 /**
90 * Returns the diameter of the point this pattern is able to detect.
91 * @return The point's diameter, in pixel, with range [3, infinity)
92 */
93 inline unsigned int diameter() const;
94
95 /**
96 * Returns the inner radius of this pattern.
97 * @return The pattern's inner radius, in pixel, with range [0, radius - 1]
98 */
99 inline unsigned int innerRadius() const;
100
101 /**
102 * Returns the stride of the frame which which this pattern has been created.
103 * @return The pattern's stride, in elements, with range [frame.width(), infinity)
104 */
105 inline unsigned int frameStrideElements() const;
106
107 /**
108 * Returns whether the outer shape of this pattern is a circle or a rectangle.
109 * @return True, if the outer shape is a circle; False, if the outer shape is a rectangle
110 */
111 inline bool isCircle() const;
112
113 /**
114 * Returns the negative offset for the most top-left pixel of the surrounding pixels.
115 * @return The pattern's negative offset, with range [0, infinity), needs to be negated
116 */
117 inline unsigned int negativeOffset() const;
118
119 /**
120 * Returns the positive offsets for all surrounding pixels starting at the top-left pixel, all in relation to the previous pixel.
121 * @return The pattern's positive offsets
122 */
123 inline const Indices32& positiveOffsets() const;
124
125 /**
126 * Returns the 2D offsets for all surrounding pixels.
127 * @return The pattern's offsets for surrounding pixels
128 */
129 inline const CV::PixelPositionsI& offsets() const;
130
131 /**
132 * Returns the normalized strength of a determined strength for this pattern.
133 * The strength is normalized due to the number of pixels this pattern uses.
134 * @param strength The strength to be normalized, with range [0, infinity)
135 * @return The normalized strength
136 */
137 inline float normalizedStrength(const unsigned int strength) const;
138
139 /**
140 * Determines the strength of a dark point candidate.
141 * A dark point has a dark center pixel surrounded by brighter pixels.
142 * @param centerPixelValue The color intensity of the center pixel, with range [0, 255]
143 * @param firstSurroundingPixel Pointer to the first surrounding pixel (top-left of the pattern), must be valid
144 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
145 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
146 * @return The strength of the point as sum of squared differences, 0 if the point is not a valid dark point
147 * @tparam tMaxCenterColorFixed The maximal color intensity of the center pixel to be considered as a dark point, with range [0, 255]
148 * @tparam tMinSurroundingColorFixed The minimal color intensity of the surrounding pixels, with range [0, tMaxCenterColorFixed)
149 */
150 template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
151 inline uint32_t determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
152
153 /**
154 * Determines the strength of a dark point candidate.
155 * A dark point has a dark center pixel surrounded by brighter pixels.
156 * @param yPoint Pointer to the center pixel in the frame, must be valid
157 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
158 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
159 * @return The strength of the point as sum of squared differences, 0 if the point is not a valid dark point
160 * @tparam tMaxCenterColorFixed The maximal color intensity of the center pixel to be considered as a dark point, with range [0, 255]
161 * @tparam tMinSurroundingColorFixed The minimal color intensity of the surrounding pixels, with range [0, tMaxCenterColorFixed)
162 */
163 template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
164 inline uint32_t determineDarkPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
165
166 /**
167 * Determines the strength of a bright point candidate.
168 * A bright point has a bright center pixel surrounded by darker pixels.
169 * @param centerPixelValue The color intensity of the center pixel, with range [0, 255]
170 * @param firstSurroundingPixel Pointer to the first surrounding pixel (top-left of the pattern), must be valid
171 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
172 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
173 * @return The strength of the point as sum of squared differences, 0 if the point is not a valid bright point
174 * @tparam tMinCenterColorFixed The minimal color intensity of the center pixel to be considered as a bright point, with range [0, 255]
175 * @tparam tMaxSurroundingColorFixed The maximal color intensity of the surrounding pixels, with range (tMinCenterColorFixed, 255]
176 */
177 template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
178 inline uint32_t determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
179
180 /**
181 * Determines the strength of a bright point candidate.
182 * A bright point has a bright center pixel surrounded by darker pixels.
183 * @param yPoint Pointer to the center pixel in the frame, must be valid
184 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
185 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
186 * @return The strength of the point as sum of squared differences, 0 if the point is not a valid bright point
187 * @tparam tMinCenterColorFixed The minimal color intensity of the center pixel to be considered as a bright point, with range [0, 255]
188 * @tparam tMaxSurroundingColorFixed The maximal color intensity of the surrounding pixels, with range (tMinCenterColorFixed, 255]
189 */
190 template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
191 inline uint32_t determineBrightPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
192
193 /**
194 * Determines the strength of a point at a sub-pixel position using bilinear interpolation.
195 * The strength is signed: positive for dark points (dark center, bright surrounding), negative for bright points.
196 * @param yFrame The frame in which the point strength will be determined, with pixel format FORMAT_Y8, must be valid
197 * @param observation The sub-pixel position of the point in the frame
198 * @param strength The resulting signed strength of the point (positive for dark points, negative for bright points)
199 * @param strict True, if all surrounding pixels have the same sign relationship to the center pixel; False otherwise
200 * @return True, if the strength could be determined successfully
201 */
202 bool determinePointStrength(const Frame& yFrame, const Vector2& observation, int32_t& strength, bool& strict) const;
203
204 /**
205 * Returns whether this pattern is valid.
206 * @return True, if so
207 */
208 inline bool isValid() const;
209
210 protected:
211
212 /**
213 * Determines the offsets for all surrounding pixels.
214 * @param radius The radius of the point pattern, with range [1, infinity)
215 * @param innerRadius The innerRadius defining a circular area around the center pixel where pixel data is excluded from use, with range [0, radius - 1]
216 * @param frameStrideElements The stride of the frame in which the point pattern is used, in elements, with range [frame.width(), infinity)
217 * @param useCircle True, if the outer shape of the point pattern is a circle; False, if the outer shape is a rectangle
218 * @param negativeOffset The resulting negative offset for the most top-left pixel of the surrounding pixels, needs to be negated
219 * @param positiveOffsets The resulting positive offsets for all surrounding pixels, starting at the top-left pixel, all in relation to the previous pixel
220 * @param offsets Optional resulting 2D offsets for all surrounding pixels
221 */
222 static bool determineOffsets(const unsigned int radius, const unsigned int innerRadius, const unsigned int frameStrideElements, const bool useCircle, Index32& negativeOffset, Indices32& positiveOffsets, CV::PixelPositionsI* offsets = nullptr);
223
224 protected:
225
226 /// The radius of the point this pattern is able to detect.
227 unsigned int radius_ = 0u;
228
229 /// The inner radius specifies a circular area around the center pixel where pixel data is excluded from use.
230 unsigned int innerRadius_ = 0u;
231
232 /// The stride of the frame which which this pattern has been created.
233 unsigned int frameStrideElements_ = 0u;
234
235 /// True, if the outer shape of this pattern is a circle; False, if the outer shape is a rectangle.
236 bool isCircle_ = false;
237
238 /// The negative offset for the most top-left pixel of the surrounding pixels.
239 Index32 negativeOffset_ = 0u;
240
241 /// The positive offsets for all surrounding pixels starting at the top-left pixel, all in relation to the previous pixel
243
244 /// The normalization factor for the strength of this pattern based on the number of pixels this pattern uses, with range (0, infinity).
245 float strengthNormalization_ = 0.0f;
246
247 /// The offsets of this pattern for all surrounding pixels.
249 };
250
251 /**
252 * Definition of a vector holding point patterns.
253 */
254 using PointPatterns = std::vector<PointPattern>;
255
256 public:
257
258 /**
259 * Creates a new point detector.
260 */
262
263 /**
264 * Detects points in a new frame.
265 * Previously detected points will be replaced.
266 * @param yFrame The frame in which the points will be detected, with pixel format FORMAT_Y8, must be valid
267 * @param worker Optional worker object to distribute the computation
268 * @return True, if succeeded
269 */
270 bool detectPoints(const Frame& yFrame, Worker* worker = nullptr);
271
272 /**
273 * Returns the points detected in the latest frame.
274 * @return The latest's frame points
275 */
276 inline const Points& points() const;
277
278 /**
279 * Returns the spatial distribution array of the points detected in the latest frame.
280 * @return The latest's frame points distribution array
281 */
282 inline const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray() const;
283
284 /**
285 * Returns the closest point to a given point.
286 * @param queryPoint The query point for which the closest point will be determined
287 * @param sign The sign of the point the closest point must have
288 * @param pointsDistributionArray The distribution array of the points to be used
289 * @param points The points from which the closest point will be determined
290 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
291 * @return The index of the closest point, -1 if no point could be found
292 */
293 static size_t closestPoint(const Vector2& queryPoint, const bool sign, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance);
294
295 /**
296 * Returns the closest points to a given point.
297 * @param pointsDistributionArray The distribution array of the points to be used
298 * @param queryPointIndex The index of the query point for which the closest points will be determined, with range [0, points.size() - 1]
299 * @param points The points from which the closest points will be determined
300 * @param indexDistancePairs The resulting index/distance pairs of the closest points
301 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
302 * @tparam tNumber The number of closest points to be determined, with range [1, infinity)
303 * @tparam tMatchSign True, to determine closest points with same sign as the query point; False, to determine closest points with any sign
304 */
305 template <unsigned int tNumber, bool tMatchSign>
306 static void closestPoints(const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const size_t queryPointIndex, const Points& points, IndexDistancePairs<tNumber>& indexDistancePairs, const Scalar maxSqrDistance);
307
308 /**
309 * Returns the two closest points to a given point.
310 * @param queryPoint The query point for which the closest points will be determined
311 * @param pointsDistributionArray The distribution array of the points to be used
312 * @param points The points from which the closest points will be determined
313 * @param closestPointIndex The resulting index of the closest point, with range [0, points.size() - 1], -1 if no point could be found
314 * @param secondClosestPointIndex The resulting index of the second closest point, with range [0, points.size() - 1], if no second closest point could be found
315 * @param closestSqrDistance The resulting square distance between the query given point and the closest point, with range [0, infinity)
316 * @param secondClosestSqrDistance The resulting square distance between the query given point and the second closest point, with range [0, infinity)
317 * @return True, if at least one closest point could be found
318 */
319 static bool closestPoints(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, Index32& closestPointIndex, Index32& secondClosestPointIndex, Scalar& closestSqrDistance, Scalar& secondClosestSqrDistance);
320
321 protected:
322
323 /**
324 * Optimizes the position of detected points and removes outliers.
325 * @param yFrame The frame in which the points have been detected, with pixel format FORMAT_Y8, must be valid
326 * @param points The points to be optimized, must be valid
327 * @param pointPatterns The point patterns which were used to detect the points, must be valid
328 * @param optimizedPoints The resulting optimized points
329 * @param worker Optional worker object to distribute the computation
330 * @return True, if succeeded
331 */
332 bool optimizePoints(const Frame& yFrame, const Points& points, const PointPatterns& pointPatterns, Points& optimizedPoints, Worker* worker = nullptr) const;
333
334 /**
335 * Detects points with several point patterns.
336 * @param yFrame The frame in which the points will be detected, with pixel format FORMAT_Y8, must be valid
337 * @param pointPatterns The point patterns to be used for point detection, at least one
338 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
339 * @param maxVariance The maximal deviation of the color intensities of the surrounding pixels, 0 to disable checking the deviation/variance
340 * @param points The resulting points
341 * @param suppressNonMaximum True, to apply a non-maximum suppression after the detection of points
342 * @param detectionScaleSteps The number of steps to be used for detection the scape, with range [1, infinity
343 * @param worker Optional worker object to distribute the computation
344 * @return True, if succeeded
345 */
346 static bool detectPoints(const Frame& yFrame, const PointPatterns& pointPatterns, const unsigned int minDifference, const unsigned int maxVariance, Points& points, const bool suppressNonMaximum, const unsigned int detectionScaleSteps = 2u, Worker* worker = nullptr);
347
348 /**
349 * Detects point candidates in a frame and adds them to a non-maximum suppression object.
350 * @param yFrame Pointer to the frame data, with pixel format FORMAT_Y8, must be valid
351 * @param yFramePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
352 * @param mask Optional pointer to a mask frame where non-zero values indicate pixels to process, nullptr to process all pixels
353 * @param pointPattern The point pattern to be used for detection, must be valid
354 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
355 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
356 * @param nonMaximumSuppression The non-maximum suppression object to which detected candidates will be added
357 * @param worker Optional worker object to distribute the computation
358 * @tparam tDarkPoint True, to detect dark points (dark center, bright surrounding); False, to detect bright points
359 */
360 template <bool tDarkPoint>
361 static void detectPointCandidates(const uint8_t* yFrame, const unsigned int yFramePaddingElements, const uint8_t* mask, const PointPattern& pointPattern, const uint8_t minDifference, const unsigned int maxVariance, CV::NonMaximumSuppressionT<uint32_t>& nonMaximumSuppression, Worker* worker = nullptr);
362
363 /**
364 * Detects point candidates in a subset of rows (worker function for parallel execution).
365 * @param yFrame Pointer to the frame data, with pixel format FORMAT_Y8, must be valid
366 * @param yFramePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
367 * @param mask Optional pointer to a mask frame where non-zero values indicate pixels to process, nullptr if tUseMask is false
368 * @param pointPatterns Pointer to the point pattern to be used for detection, must be valid
369 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
370 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
371 * @param nonMaximumSuppression Pointer to the non-maximum suppression object to which detected candidates will be added, must be valid
372 * @param firstColumn The first column to be processed, with range [0, width - 1]
373 * @param numberColumns The number of columns to be processed, with range [1, width - firstColumn]
374 * @param firstRow The first row to be processed, with range [0, height - 1]
375 * @param numberRows The number of rows to be processed, with range [1, height - firstRow]
376 * @tparam tDarkPoint True, to detect dark points (dark center, bright surrounding); False, to detect bright points
377 * @tparam tUseMask True, if a mask is used; False, if no mask is used
378 */
379 template <bool tDarkPoint, bool tUseMask>
380 static void detectPointCandidatesSubset(const uint8_t* yFrame, const unsigned int yFramePaddingElements, const uint8_t* mask, const PointPattern* pointPatterns, const uint8_t minDifference, const unsigned int maxVariance, CV::NonMaximumSuppressionT<uint32_t>* nonMaximumSuppression, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows);
381
382 /**
383 * Determines the best matching radius for a detected point by testing smaller point patterns.
384 * @param yFrame Pointer to the frame data, with pixel format FORMAT_Y8, must be valid
385 * @param width The width of the frame, in pixels, with range [1, infinity)
386 * @param height The height of the frame, in pixels, with range [1, infinity)
387 * @param yFramePaddingElements The number of padding elements at the end of each frame row, in elements, with range [0, infinity)
388 * @param pixelPosition The pixel position of the detected point, must be inside the frame
389 * @param currentRadius The current radius of the detected point, with range [1, infinity)
390 * @param pointPatterns Pointer to an array of point patterns with increasing radii, must be valid
391 * @param numberPointPatterns The number of point patterns in the array, with range [2, infinity)
392 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
393 * @param maxVariance The maximal variance of the color intensities of the surrounding pixels, 0 to disable checking the variance
394 * @param radius The resulting best matching radius for the point
395 * @param strength The resulting strength of the point at the best matching radius
396 * @return True, if a smaller radius was found; False, if the current radius is the best match
397 * @tparam tDarkPoint True, to test for dark points (dark center, bright surrounding); False, to test for bright points
398 */
399 template <bool tDarkPoint>
400 static bool determinePointRadius(const uint8_t* yFrame, const unsigned int width, const unsigned int height, const unsigned int yFramePaddingElements, const CV::PixelPosition& pixelPosition, const unsigned int currentRadius, const PointPattern* pointPatterns, const size_t numberPointPatterns, const uint8_t minDifference, const unsigned int maxVariance, unsigned int& radius, unsigned int& strength);
401
402 /**
403 * Removes duplicated points from a given set of points.
404 * @param width The width of the frame in which the points have been detected, in pixel, with range [1, infinity)
405 * @param height The height of the frame in which the points have been detected, in pixel, with range [1, infinity)
406 * @param points The points from which the duplicated points will be removed
407 * @param maxDistance The maximal distance between two points to be considered as duplicated, with range [0, infinity)
408 */
409 static void removeDuplicatedPoints(const unsigned int width, const unsigned int height, Points& points, const Scalar maxDistance);
410
411 /**
412 * Returns whether a query point is close to another point.
413 * @param queryPoint The query point to check
414 * @param pointsDistributionArray The distribution array of the points to be used
415 * @param points The points from which the closest point will be determined
416 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
417 * @return True, if so
418 */
419 static bool hasClosePoint(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance);
420
421 /**
422 * Returns the closest points to a query point.
423 * @param queryPoint The query point for which the closest points will be determined
424 * @param pointsDistributionArray The distribution array of the points to be used
425 * @param points The points from which the closest point will be determined
426 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
427 * @param pointIndices The resulting indices of the closest points
428 * @return True, if at least one closest point could be found
429 */
430 static bool closestPoints(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance, Indices32& pointIndices);
431
432 /**
433 * Creates the point patterns with increasing radii.
434 * @param radius The maximal radius of the point patterns, with range [1, infinity)
435 * @param innerRadius The innerRadius defining a circular area around the center pixel where pixel data is excluded from use, with range [0, radius - 1]
436 * @param useCircle True, if the outer shape of the point pattern is a circle; False, if the outer shape is a rectangle
437 * @param frameStrideElements The stride of the frame in which the point patterns will be used, in elements, with range [frame.width(), infinity)
438 * @return The resulting point patterns
439 */
440 static PointPatterns createPointPatterns(const unsigned int radius, const unsigned int innerRadius, const bool useCircle, const unsigned int frameStrideElements);
441
442 /**
443 * Updates the point patterns for a specified frame stride.
444 * In case the frame stride is identical to the frame stride of the point patterns, the point patterns will not change.
445 * @param pointPatterns The point patterns to be updated, must be valid
446 * @param frameStrideElements The stride of the frame in which the point patterns will be used, in elements, with range [frame.width(), infinity)
447 */
448 static void updatePointPatterns(PointPatterns& pointPatterns, const unsigned int frameStrideElements);
449
450 /**
451 * Paints a point pattern into a frame.
452 * @param yFrame The frame in which the point pattern will be painted, with pixel format FORMAT_Y8, must be valid
453 * @param radius The radius of the point pattern, with range [1, infinity)
454 * @param pointColor The color of the point pattern, with range [0, 255]
455 */
456 static bool paintPointPattern(Frame& yFrame, const unsigned int radius, const uint8_t pointColor = 0x00u);
457
458 protected:
459
460 /// The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255].
461 unsigned int minDifference_ = 5u;
462
463 /// The maximal deviation of the color intensities of the surrounding pixels, 0 to disable checking the deviation/variance.
464 unsigned int maxDeviation_ = 30u;
465
466 /// The maximal distance between two points to be considered as duplicated, with range [0, infinity).
467 Scalar maxDistanceBetweenDuplicatePoints_ = Scalar(2);
468
469 /// The point patterns to be used for point detection.
471
472 /// Rough intermediate points.
474
475 /// The precise points detected in the latest frame.
477
478 /// The spatial distribution array of the points detected in the latest frame.
480
481 /// The frame with all images of point pattern with individual radii.
483
484 /// The width and height of the point pattern images.
485 static constexpr unsigned int pointPatternImageSize_ = 31u;
486};
487
489{
490 return radius_;
491}
492
494{
495 ocean_assert(isValid());
496 return radius_ * 2u + 1u;
497}
498
500{
501 return innerRadius_;
502}
503
505{
506 return frameStrideElements_;
507}
508
510{
511 return isCircle_;
512}
513
515{
516 return negativeOffset_;
517}
518
520{
521 return positiveOffsets_;
522}
523
525{
526 return offsets_;
527}
528
529inline float LegacyPointDetector::PointPattern::normalizedStrength(const unsigned int strength) const
530{
531 ocean_assert(strengthNormalization_ != 0.0f);
532
533 return float(strength) * strengthNormalization_;
534}
535
536template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
537inline uint32_t LegacyPointDetector::PointPattern::determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance) const
538{
539 ocean_assert(isValid());
540 ocean_assert(firstSurroundingPixel != nullptr);
541
542 static_assert(tMinSurroundingColorFixed < tMaxCenterColorFixed);
543
544 if (centerPixelValue > tMaxCenterColorFixed) // the center pixel should have a certain amount of darkness
545 {
546 return 0u;
547 }
548
549 ocean_assert(centerPixelValue + minDifference <= 0xFFu);
550 const uint8_t minSurroundingColor = std::max(tMinSurroundingColorFixed, uint8_t(centerPixelValue + minDifference)); // the surrounding pixels should be brighter than the center pixel and brighter than certain threshold in general
551
552 uint32_t sumSqrDifferences = 0u;
553
554 const uint8_t* surroundingPixel = firstSurroundingPixel;
555
556 VarianceT<uint32_t> variance;
557
558 for (const Index32& positiveOffset : positiveOffsets_)
559 {
560 surroundingPixel += positiveOffset;
561
562 const uint8_t surroundingPixelValue = *surroundingPixel;
563
564 if (surroundingPixelValue < minSurroundingColor)
565 {
566 return 0u;
567 }
568
569 variance.add(uint32_t(surroundingPixelValue));
570
571 ocean_assert(surroundingPixelValue > centerPixelValue);
572
573 const uint32_t difference = surroundingPixelValue - centerPixelValue;
574
575 sumSqrDifferences += difference * difference;
576 }
577
578 if (sumSqrDifferences != 0u && (maxVariance == 0u || variance.variance() <= maxVariance))
579 {
580 return sumSqrDifferences;
581 }
582
583 return 0u;
584}
585
586template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
587inline uint32_t LegacyPointDetector::PointPattern::determineDarkPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance) const
588{
589 ocean_assert(yPoint != nullptr);
590
591 const uint8_t centerPixelValue = *yPoint;
592
593 return determineDarkPointStrength<tMaxCenterColorFixed, tMinSurroundingColorFixed>(centerPixelValue, yPoint - negativeOffset_, minDifference, maxVariance);
594}
595
596template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
597inline uint32_t LegacyPointDetector::PointPattern::determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance) const
598{
599 ocean_assert(isValid());
600 ocean_assert(firstSurroundingPixel != nullptr);
601
602 static_assert(tMinCenterColorFixed < tMaxSurroundingColorFixed);
603
604 if (centerPixelValue < tMinCenterColorFixed) // the center pixel should have a certain amount of brightness
605 {
606 return 0u;
607 }
608
609 ocean_assert(int32_t(centerPixelValue) - int32_t(minDifference) >= 0);
610 const uint8_t maxSurroundingColor = std::min(tMaxSurroundingColorFixed, uint8_t(centerPixelValue - minDifference)); // the surrounding pixels should be darker than the center pixel and darker than certain threshold in general
611
612 uint32_t sumSqrDifferences = 0u;
613
614 const uint8_t* surroundingPixel = firstSurroundingPixel;
615
616 VarianceT<uint32_t> variance;
617
618 for (const Index32& positiveOffset : positiveOffsets_)
619 {
620 surroundingPixel += positiveOffset;
621
622 const uint8_t surroundingPixelValue = *surroundingPixel;
623
624 if (surroundingPixelValue > maxSurroundingColor)
625 {
626 return 0u;
627 }
628
629 variance.add(uint32_t(surroundingPixelValue));
630
631 ocean_assert(surroundingPixelValue < centerPixelValue);
632
633 const uint32_t difference = centerPixelValue - surroundingPixelValue;
634
635 sumSqrDifferences += difference * difference;
636 }
637
638 if (sumSqrDifferences != 0u && (maxVariance == 0u || variance.variance() <= maxVariance))
639 {
640 return sumSqrDifferences;
641 }
642
643 return 0u;
644}
645
646template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
647inline uint32_t LegacyPointDetector::PointPattern::determineBrightPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance) const
648{
649 ocean_assert(yPoint != nullptr);
650
651 const uint8_t centerPixelValue = *yPoint;
652
653 return determineBrightPointStrength<tMinCenterColorFixed, tMaxSurroundingColorFixed>(centerPixelValue, yPoint - negativeOffset_, minDifference, maxVariance);
654}
655
657{
658 ocean_assert(radius_ == 0u || innerRadius_ < radius_);
659 ocean_assert(radius_ == 0u || frameStrideElements_ != 0u);
660
661 return radius_ >= 1u;
662}
663
664template <unsigned int tNumber, bool tMatchSign>
666{
667 static_assert(tNumber >= 1u, "Invalid number of points!");
668
669 ocean_assert(indexDistancePairs.empty());
670 ocean_assert(queryPointIndex < points.size());
671
672 const Vector2& point = points[queryPointIndex].observation();
673
674 const unsigned int xBinCenter = pointsDistributionArray.horizontalBin(point.x());
675 const unsigned int yBinCenter = pointsDistributionArray.verticalBin(point.y());
676
677 for (unsigned int xBin = (unsigned int)(std::max(0, int(xBinCenter) - 1)); xBin < std::min(xBinCenter + 2u, pointsDistributionArray.horizontalBins()); ++xBin)
678 {
679 for (unsigned int yBin = (unsigned int)(std::max(0, int(yBinCenter) - 1)); yBin < std::min(yBinCenter + 2u, pointsDistributionArray.verticalBins()); ++yBin)
680 {
681 const Indices32& indices = pointsDistributionArray(xBin, yBin);
682
683 for (const Index32& index : indices)
684 {
685 if (index == Index32(queryPointIndex))
686 {
687 continue;
688 }
689
690 if constexpr (tMatchSign)
691 {
692 if (points[queryPointIndex].sign() != points[index].sign())
693 {
694 continue;
695 }
696 }
697
698 const Scalar sqrDistance = point.sqrDistance(points[index].observation());
699
700 if (sqrDistance > maxSqrDistance)
701 {
702 continue;
703 }
704
705 bool inserted = false;
706
707 if (!indexDistancePairs.empty() && sqrDistance < indexDistancePairs.back().second)
708 {
709 for (size_t nCandidate = 0; nCandidate < indexDistancePairs.size(); ++nCandidate)
710 {
711 if (sqrDistance < indexDistancePairs[nCandidate].second)
712 {
713 if (indexDistancePairs.size() != tNumber)
714 {
715 indexDistancePairs.weakResize(indexDistancePairs.size() + 1);
716 }
717
718 for (size_t n = indexDistancePairs.size() - 1; n > nCandidate; --n)
719 {
720 indexDistancePairs[n] = indexDistancePairs[n - 1];
721 }
722
723 indexDistancePairs[nCandidate] = IndexDistancePair(index, sqrDistance);
724
725 inserted = true;
726 break;
727
728 }
729 }
730 }
731
732 if (!inserted && indexDistancePairs.size() < tNumber)
733 {
734 indexDistancePairs.pushBack(IndexDistancePair(index, sqrDistance));
735 }
736 }
737 }
738 }
739}
740
742{
743 return points_;
744}
745
750
751}
752
753}
754
755}
756
757#endif // META_OCEAN_CV_CALIBRATION_LEGACY_POINT_DETECTOR_H
This class implements debug elements for the calibration library.
Definition CalibrationDebugElements.h:43
This class implements a pattern for fast point detection.
Definition LegacyPointDetector.h:64
const CV::PixelPositionsI & offsets() const
Returns the 2D offsets for all surrounding pixels.
Definition LegacyPointDetector.h:524
PointPattern(const unsigned int radius, const unsigned int innerRadius, const unsigned int frameStrideElements, const bool useCircle=true)
Creates a new point pattern.
bool determinePointStrength(const Frame &yFrame, const Vector2 &observation, int32_t &strength, bool &strict) const
Determines the strength of a point at a sub-pixel position using bilinear interpolation.
const Indices32 & positiveOffsets() const
Returns the positive offsets for all surrounding pixels starting at the top-left pixel,...
Definition LegacyPointDetector.h:519
unsigned int frameStrideElements() const
Returns the stride of the frame which which this pattern has been created.
Definition LegacyPointDetector.h:504
unsigned int radius_
The radius of the point this pattern is able to detect.
Definition LegacyPointDetector.h:227
static bool determineOffsets(const unsigned int radius, const unsigned int innerRadius, const unsigned int frameStrideElements, const bool useCircle, Index32 &negativeOffset, Indices32 &positiveOffsets, CV::PixelPositionsI *offsets=nullptr)
Determines the offsets for all surrounding pixels.
unsigned int diameter() const
Returns the diameter of the point this pattern is able to detect.
Definition LegacyPointDetector.h:493
unsigned int negativeOffset() const
Returns the negative offset for the most top-left pixel of the surrounding pixels.
Definition LegacyPointDetector.h:514
unsigned int radius() const
Returns the radius of the point this pattern is able to detect.
Definition LegacyPointDetector.h:488
uint32_t determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t *firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance=0u) const
Determines the strength of a bright point candidate.
Definition LegacyPointDetector.h:597
unsigned int innerRadius() const
Returns the inner radius of this pattern.
Definition LegacyPointDetector.h:499
Indices32 positiveOffsets_
The positive offsets for all surrounding pixels starting at the top-left pixel, all in relation to th...
Definition LegacyPointDetector.h:242
uint32_t determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t *firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance=0u) const
Determines the strength of a dark point candidate.
Definition LegacyPointDetector.h:537
PointPattern(const PointPattern &pointPattern, const unsigned int frameStrideElements)
Creates a new point pattern with same properties as a given point pattern but with different frame st...
CV::PixelPositionsI offsets_
The offsets of this pattern for all surrounding pixels.
Definition LegacyPointDetector.h:248
bool isValid() const
Returns whether this pattern is valid.
Definition LegacyPointDetector.h:656
bool isCircle() const
Returns whether the outer shape of this pattern is a circle or a rectangle.
Definition LegacyPointDetector.h:509
float normalizedStrength(const unsigned int strength) const
Returns the normalized strength of a determined strength for this pattern.
Definition LegacyPointDetector.h:529
This class implements a point detector for marker points.
Definition LegacyPointDetector.h:39
static bool determinePointRadius(const uint8_t *yFrame, const unsigned int width, const unsigned int height, const unsigned int yFramePaddingElements, const CV::PixelPosition &pixelPosition, const unsigned int currentRadius, const PointPattern *pointPatterns, const size_t numberPointPatterns, const uint8_t minDifference, const unsigned int maxVariance, unsigned int &radius, unsigned int &strength)
Determines the best matching radius for a detected point by testing smaller point patterns.
std::pair< Index32, Scalar > IndexDistancePair
Definition of a pair combining an index with a distance.
Definition LegacyPointDetector.h:47
static bool closestPoints(const Vector2 &queryPoint, const Geometry::SpatialDistribution::DistributionArray &pointsDistributionArray, const Points &points, const Scalar maxSqrDistance, Indices32 &pointIndices)
Returns the closest points to a query point.
static bool hasClosePoint(const Vector2 &queryPoint, const Geometry::SpatialDistribution::DistributionArray &pointsDistributionArray, const Points &points, const Scalar maxSqrDistance)
Returns whether a query point is close to another point.
static bool closestPoints(const Vector2 &queryPoint, const Geometry::SpatialDistribution::DistributionArray &pointsDistributionArray, const Points &points, Index32 &closestPointIndex, Index32 &secondClosestPointIndex, Scalar &closestSqrDistance, Scalar &secondClosestSqrDistance)
Returns the two closest points to a given point.
static size_t closestPoint(const Vector2 &queryPoint, const bool sign, const Geometry::SpatialDistribution::DistributionArray &pointsDistributionArray, const Points &points, const Scalar maxSqrDistance)
Returns the closest point to a given point.
Frame yPointPatternImages_
The frame with all images of point pattern with individual radii.
Definition LegacyPointDetector.h:482
static PointPatterns createPointPatterns(const unsigned int radius, const unsigned int innerRadius, const bool useCircle, const unsigned int frameStrideElements)
Creates the point patterns with increasing radii.
const Points & points() const
Returns the points detected in the latest frame.
Definition LegacyPointDetector.h:741
static void removeDuplicatedPoints(const unsigned int width, const unsigned int height, Points &points, const Scalar maxDistance)
Removes duplicated points from a given set of points.
Points roughPoints_
Rough intermediate points.
Definition LegacyPointDetector.h:473
const Geometry::SpatialDistribution::DistributionArray & pointsDistributionArray() const
Returns the spatial distribution array of the points detected in the latest frame.
Definition LegacyPointDetector.h:746
static void detectPointCandidates(const uint8_t *yFrame, const unsigned int yFramePaddingElements, const uint8_t *mask, const PointPattern &pointPattern, const uint8_t minDifference, const unsigned int maxVariance, CV::NonMaximumSuppressionT< uint32_t > &nonMaximumSuppression, Worker *worker=nullptr)
Detects point candidates in a frame and adds them to a non-maximum suppression object.
Points points_
The precise points detected in the latest frame.
Definition LegacyPointDetector.h:476
static void updatePointPatterns(PointPatterns &pointPatterns, const unsigned int frameStrideElements)
Updates the point patterns for a specified frame stride.
LegacyPointDetector::PointPatterns pointPatterns_
The point patterns to be used for point detection.
Definition LegacyPointDetector.h:470
static bool paintPointPattern(Frame &yFrame, const unsigned int radius, const uint8_t pointColor=0x00u)
Paints a point pattern into a frame.
std::vector< PointPattern > PointPatterns
Definition of a vector holding point patterns.
Definition LegacyPointDetector.h:254
static bool detectPoints(const Frame &yFrame, const PointPatterns &pointPatterns, const unsigned int minDifference, const unsigned int maxVariance, Points &points, const bool suppressNonMaximum, const unsigned int detectionScaleSteps=2u, Worker *worker=nullptr)
Detects points with several point patterns.
static void closestPoints(const Geometry::SpatialDistribution::DistributionArray &pointsDistributionArray, const size_t queryPointIndex, const Points &points, IndexDistancePairs< tNumber > &indexDistancePairs, const Scalar maxSqrDistance)
Returns the closest points to a given point.
Definition LegacyPointDetector.h:665
bool optimizePoints(const Frame &yFrame, const Points &points, const PointPatterns &pointPatterns, Points &optimizedPoints, Worker *worker=nullptr) const
Optimizes the position of detected points and removes outliers.
bool detectPoints(const Frame &yFrame, Worker *worker=nullptr)
Detects points in a new frame.
static void detectPointCandidatesSubset(const uint8_t *yFrame, const unsigned int yFramePaddingElements, const uint8_t *mask, const PointPattern *pointPatterns, const uint8_t minDifference, const unsigned int maxVariance, CV::NonMaximumSuppressionT< uint32_t > *nonMaximumSuppression, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows)
Detects point candidates in a subset of rows (worker function for parallel execution).
LegacyPointDetector()=default
Creates a new point detector.
Geometry::SpatialDistribution::DistributionArray pointsDistributionArray_
The spatial distribution array of the points detected in the latest frame.
Definition LegacyPointDetector.h:479
This class implements the possibility to find local maximum in a 2D array by applying a non-maximum-s...
Definition NonMaximumSuppression.h:138
This class implements Ocean's image class.
Definition Frame.h:1879
unsigned int horizontalBins() const
Returns the number of horizontal distribution bins.
Definition SpatialDistribution.h:1122
int horizontalBin(const Scalar x) const
Returns the horizontal bin of a given horizontal position.
Definition SpatialDistribution.h:1148
int verticalBin(const Scalar y) const
Returns the vertical bin of a given vertical position.
Definition SpatialDistribution.h:1154
unsigned int verticalBins() const
Returns the number of vertical distribution bins.
Definition SpatialDistribution.h:1127
This class implements a distribution array.
Definition SpatialDistribution.h:272
This class implements a static vector that has a fixed capacity.
Definition StaticVector.h:25
size_t size() const
Returns the size of this vector.
Definition StaticVector.h:390
void weakResize(const size_t size)
Resizes this vector.
Definition StaticVector.h:645
bool empty() const
Returns whether this vector hold no element.
Definition StaticVector.h:584
void pushBack(const T &value)
Adds a new element to this vector.
Definition StaticVector.h:402
const T & back() const
Returns the last elements of this vector.
Definition StaticVector.h:544
This class allows to determine the variance in a given data set.
Definition Variance.h:56
void add(const T &value)
Adds a new value.
Definition Variance.h:148
T variance() const
Returns the variance of the data set.
Definition Variance.h:200
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
T sqrDistance(const VectorT2< T > &right) const
Returns the square distance between this 2D position and a second 2D position.
Definition Vector2.h:645
This class implements a worker able to distribute function calls over different threads.
Definition Worker.h:33
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition Base.h:96
uint32_t Index32
Definition of a 32 bit index value.
Definition Base.h:84
std::vector< PixelPositionI > PixelPositionsI
Definition of a vector holding pixel positions (with positive and negative coordinate values).
Definition PixelPosition.h:53
std::vector< Point > Points
Definition of a vector holding points.
Definition cv/calibration/Point.h:31
float Scalar
Definition of a scalar type.
Definition Math.h:129
The namespace covering the entire Ocean framework.
Definition Accessor.h:15