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