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 * **TODO**
127 */
128 template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
129 inline uint32_t determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
130
131 /**
132 * **TODO**
133 */
134 template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
135 inline uint32_t determineDarkPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
136
137 /**
138 * **TODO**
139 */
140 template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
141 inline uint32_t determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
142
143 /**
144 * **TODO**
145 */
146 template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
147 inline uint32_t determineBrightPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance = 0u) const;
148
149 /**
150 * **TODO**
151 */
152 bool determinePointStrength(const Frame& yFrame, const CV::PixelPosition& observation, int32_t& strength, bool& strict) const;
153
154 /**
155 * **TODO**
156 */
157 bool determinePointStrength(const Frame& yFrame, const Vector2& observation, int32_t& strength, bool& strict) const;
158
159 /**
160 * Returns whether this pattern is valid.
161 * @return True, if so
162 */
163 inline bool isValid() const;
164
165 protected:
166
167 /**
168 * Determines the offsets for all surrounding pixels.
169 * @param radius The radius of the point pattern, with range [1, infinity)
170 * @param innerRadius The innerRadius defining a circular area around the center pixel where pixel data is excluded from use, with range [0, radius - 1]
171 * @param frameStrideElements The stride of the frame in which the point pattern is used, in elements, with range [frame.width(), infinity)
172 * @param useCircle True, if the outer shape of the point pattern is a circle; False, if the outer shape is a rectangle
173 * @param negativeOffset The resulting negative offset for the most top-left pixel of the surrounding pixels, needs to be negated
174 * @param positiveOffsets The resulting positive offsets for all surrounding pixels, starting at the top-left pixel, all in relation to the previous pixel
175 * @param offsets Optional resulting 2D offsets for all surrounding pixels
176 */
177 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);
178
179 protected:
180
181 /// The radius of the point this pattern is able to detect.
182 unsigned int radius_ = 0u;
183
184 /// The inner radius specifies a circular area around the center pixel where pixel data is excluded from use.
185 unsigned int innerRadius_ = 0u;
186
187 /// The stride of the frame which which this pattern has been created.
188 unsigned int frameStrideElements_ = 0u;
189
190 /// True, if the outer shape of this pattern is a circle; False, if the outer shape is a rectangle.
191 bool isCircle_ = false;
192
193 /// The negative offset for the most top-left pixel of the surrounding pixels.
194 Index32 negativeOffset_ = 0u;
195
196 /// The positive offsets for all surrounding pixels starting at the top-left pixel, all in relation to the previous pixel
198
199 /// The normalization factor for the strength of this pattern based on the number of pixels this pattern uses, with range (0, infinity).
200 float strengthNormalization_ = 0.0f;
201
202 /// The offsets of this pattern for all surrounding pixels.
204 };
205
206 /**
207 * Definition of a vector holding point patterns.
208 */
209 using PointPatterns = std::vector<PointPattern>;
210
211 /**
212 * Definition of a pair combining an index with a distance.
213 */
214 using IndexDistancePair = std::pair<Index32, Scalar>;
215
216 /**
217 * Definition of a static vector holding IndexDistancePair objects.
218 * @tparam tNumber The number of elements the vector can hold at most, with range [1, infinity)
219 */
220 template <unsigned int tNumber>
222
223 public:
224
225 /**
226 * Creates a new point detector.
227 */
228 PointDetector() = default;
229
230 /**
231 * Detects points in a new frame.
232 * Previously detected points will be replaced.
233 * @param yFrame The frame in which the points will be detected, with pixel format FORMAT_Y8, must be valid
234 * @param worker Optional worker object to distribute the computation
235 * @return True, if succeeded
236 */
237 bool detectPoints(const Frame& yFrame, Worker* worker = nullptr);
238
239 /**
240 * Returns the points detected in the latest frame.
241 * @return The latest's frame points
242 */
243 inline const Points& points() const;
244
245 /**
246 * Returns the spatial distribution array of the points detected in the latest frame.
247 * @return The latest's frame points distribution array
248 */
249 inline const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray() const;
250
251 /**
252 * Returns the closest point to a given point.
253 * @param queryPoint The query point for which the closest point will be determined
254 * @param sign The sign of the point the closest point must have
255 * @param pointsDistributionArray The distribution array of the points to be used
256 * @param points The points from which the closest point will be determined
257 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
258 * @return The index of the closest point, -1 if no point could be found
259 */
260 static size_t closestPoint(const Vector2& queryPoint, const bool sign, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance);
261
262 /**
263 * Returns the closest points to a given point.
264 * @param pointsDistributionArray The distribution array of the points to be used
265 * @param queryPointIndex The index of the query point for which the closest points will be determined, with range [0, points.size() - 1]
266 * @param points The points from which the closest points will be determined
267 * @param indexDistancePairs The resulting index/distance pairs of the closest points
268 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
269 * @tparam tNumber The number of closest points to be determined, with range [1, infinity)
270 * @tparam tMatchSign True, to determine closest points with same sign as the query point; False, to determine closest points with any sign
271 */
272 template <unsigned int tNumber, bool tMatchSign>
273 static void closestPoints(const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const size_t queryPointIndex, const Points& points, IndexDistancePairs<tNumber>& indexDistancePairs, const Scalar maxSqrDistance);
274
275 /**
276 * Returns the two closest points to a given point.
277 * @param queryPoint The query point for which the closest points will be determined
278 * @param pointsDistributionArray The distribution array of the points to be used
279 * @param points The points from which the closest points will be determined
280 * @param closestPointIndex The resulting index of the closest point, with range [0, points.size() - 1], -1 if no point could be found
281 * @param secondClosestPointIndex The resulting index of the second closest point, with range [0, points.size() - 1], if no second closest point could be found
282 * @param closestSqrDistance The resulting square distance between the query given point and the closest point, with range [0, infinity)
283 * @param secondClosestSqrDistance The resulting square distance between the query given point and the second closest point, with range [0, infinity)
284 * @return True, if at least one closest point could be found
285 */
286 static bool closestPoints(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, Index32& closestPointIndex, Index32& secondClosestPointIndex, Scalar& closestSqrDistance, Scalar& secondClosestSqrDistance);
287
288 protected:
289
290 /**
291 * Optimizes the position of detected points and removes outliers.
292 * @param yFrame The frame in which the points have been detected, with pixel format FORMAT_Y8, must be valid
293 * @param points The points to be optimized, must be valid
294 * @param pointPatterns The point patterns which were used to detect the points, must be valid
295 * @param optimizedPoints The resulting optimized points
296 * @param worker Optional worker object to distribute the computation
297 * @return True, if succeeded
298 */
299 bool optimizePoints(const Frame& yFrame, const Points& points, const PointPatterns& pointPatterns, Points& optimizedPoints, Worker* worker = nullptr) const;
300
301 /**
302 * Detects points with several point patterns.
303 * @param yFrame The frame in which the points will be detected, with pixel format FORMAT_Y8, must be valid
304 * @param pointPatterns The point patterns to be used for point detection, at least one
305 * @param minDifference The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255]
306 * @param maxVariance The maximal deviation of the color intensities of the surrounding pixels, 0 to disable checking the deviation/variance
307 * @param points The resulting points
308 * @param suppressNonMaximum True, to apply a non-maximum suppression after the detection of points
309 * @param detectionScaleSteps The number of steps to be used for detection the scape, with range [1, infinity
310 * @param worker Optional worker object to distribute the computation
311 * @return True, if succeeded
312 */
313 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);
314
315 /**
316 * **TODO**
317 */
318 template <bool tDarkPoint>
319 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::NonMaximumSuppression<uint32_t>& nonMaximumSuppression, Worker* worker = nullptr);
320
321 /**
322 * **TODO**
323 */
324 template <bool tDarkPoint, bool tUseMask>
325 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::NonMaximumSuppression<uint32_t>* nonMaximumSuppression, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows);
326
327 /**
328 * **TODO**
329 */
330 template <bool tDarkPoint>
331 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);
332
333 /**
334 * Removes duplicated points from a given set of points.
335 * @param width The width of the frame in which the points have been detected, in pixel, with range [1, infinity)
336 * @param height The height of the frame in which the points have been detected, in pixel, with range [1, infinity)
337 * @param points The points from which the duplicated points will be removed
338 * @param maxDistance The maximal distance between two points to be considered as duplicated, with range [0, infinity)
339 */
340 static void removeDuplicatedPoints(const unsigned int width, const unsigned int height, Points& points, const Scalar maxDistance);
341
342 /**
343 * Returns whether a query point is close to another point.
344 * @param queryPoint The query point to check
345 * @param pointsDistributionArray The distribution array of the points to be used
346 * @param points The points from which the closest point will be determined
347 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
348 * @return True, if so
349 */
350 static bool hasClosePoint(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance);
351
352 /**
353 * Returns the closest points to a query point.
354 * @param queryPoint The query point for which the closest points will be determined
355 * @param pointsDistributionArray The distribution array of the points to be used
356 * @param points The points from which the closest point will be determined
357 * @param maxSqrDistance The maximal square distance between the given point and the closest point, with range [0, infinity)
358 * @param pointIndices The resulting indices of the closest points
359 * @return True, if at least one closest point could be found
360 */
361 static bool closestPoints(const Vector2& queryPoint, const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const Points& points, const Scalar maxSqrDistance, Indices32& pointIndices);
362
363 /**
364 * Creates the point patterns with increasing radii.
365 * @param radius The maximal radius of the point patterns, with range [1, infinity)
366 * @param innerRadius The innerRadius defining a circular area around the center pixel where pixel data is excluded from use, with range [0, radius - 1]
367 * @param useCircle True, if the outer shape of the point pattern is a circle; False, if the outer shape is a rectangle
368 * @param frameStrideElements The stride of the frame in which the point patterns will be used, in elements, with range [frame.width(), infinity)
369 * @return The resulting point patterns
370 */
371 static PointPatterns createPointPatterns(const unsigned int radius, const unsigned int innerRadius, const bool useCircle, const unsigned int frameStrideElements);
372
373 /**
374 * Updates the point patterns for a specified frame stride.
375 * In case the frame stride is identical to the frame stride of the point patterns, the point patterns will not change.
376 * @param pointPatterns The point patterns to be updated, must be valid
377 * @param frameStrideElements The stride of the frame in which the point patterns will be used, in elements, with range [frame.width(), infinity)
378 */
379 static void updatePointPatterns(PointPatterns& pointPatterns, const unsigned int frameStrideElements);
380
381 /**
382 * Paints a point pattern into a frame.
383 * @param yFrame The frame in which the point pattern will be painted, with pixel format FORMAT_Y8, must be valid
384 * @param radius The radius of the point pattern, with range [1, infinity)
385 * @param pointColor The color of the point pattern, with range [0, 255]
386 */
387 static bool paintPointPattern(Frame& yFrame, const unsigned int radius, const uint8_t pointColor = 0x00u);
388
389 protected:
390
391 /// The minimal color intensity difference between the center pixel and the surrounding pixels, with range [0, 255].
392 unsigned int minDifference_ = 5u;
393
394 /// The maximal deviation of the color intensities of the surrounding pixels, 0 to disable checking the deviation/variance.
395 unsigned int maxDeviation_ = 30u;
396
397 /// The maximal distance between two points to be considered as duplicated, with range [0, infinity).
398 Scalar maxDistanceBetweenDuplicatePoints_ = Scalar(2);
399
400 /// The point patterns to be used for point detection.
402
403 /// Rough intermediate points.
405
406 /// The precise points detected in the latest frame.
408
409 /// The spatial distribution array of the points detected in the latest frame.
411
412 /// The frame with all images of point pattern with individual radii.
414
415 /// The width and height of the point pattern images.
416 static constexpr unsigned int pointPatternImageSize_ = 31u;
417};
418
419inline unsigned int PointDetector::PointPattern::radius() const
420{
421 return radius_;
422}
423
424inline unsigned int PointDetector::PointPattern::diameter() const
425{
426 ocean_assert(isValid());
427 return radius_ * 2u + 1u;
428}
429
431{
432 return innerRadius_;
433}
434
436{
437 return frameStrideElements_;
438}
439
441{
442 return isCircle_;
443}
444
446{
447 return negativeOffset_;
448}
449
451{
452 return positiveOffsets_;
453}
454
456{
457 return offsets_;
458}
459
460inline float PointDetector::PointPattern::normalizedStrength(const unsigned int strength) const
461{
462 ocean_assert(strengthNormalization_ != 0.0f);
463
464 return float(strength) * strengthNormalization_;
465}
466
467template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
468inline uint32_t PointDetector::PointPattern::determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance) const
469{
470 ocean_assert(isValid());
471 ocean_assert(firstSurroundingPixel != nullptr);
472
473 static_assert(tMinSurroundingColorFixed < tMaxCenterColorFixed);
474
475 if (centerPixelValue > tMaxCenterColorFixed) // the center pixel should have a certain amount of darkness
476 {
477 return 0u;
478 }
479
480 ocean_assert(centerPixelValue + minDifference <= 0xFFu);
481 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
482
483 uint32_t sumSqrDifferences = 0u;
484
485 const uint8_t* surroundingPixel = firstSurroundingPixel;
486
487 VarianceT<uint32_t> variance;
488
489 for (const Index32& positiveOffset : positiveOffsets_)
490 {
491 surroundingPixel += positiveOffset;
492
493 const uint8_t surroundingPixelValue = *surroundingPixel;
494
495 if (surroundingPixelValue < minSurroundingColor)
496 {
497 return 0u;
498 }
499
500 variance.add(uint32_t(surroundingPixelValue));
501
502 ocean_assert(surroundingPixelValue > centerPixelValue);
503
504 const uint32_t difference = surroundingPixelValue - centerPixelValue;
505
506 sumSqrDifferences += difference * difference;
507 }
508
509 if (sumSqrDifferences != 0u && (maxVariance == 0u || variance.variance() <= maxVariance))
510 {
511 return sumSqrDifferences;
512 }
513
514 return 0u;
515}
516
517template <uint8_t tMaxCenterColorFixed, uint8_t tMinSurroundingColorFixed>
518inline uint32_t PointDetector::PointPattern::determineDarkPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance) const
519{
520 ocean_assert(yPoint != nullptr);
521
522 const uint8_t centerPixelValue = *yPoint;
523
524 return determineDarkPointStrength<tMaxCenterColorFixed, tMinSurroundingColorFixed>(centerPixelValue, yPoint - negativeOffset_, minDifference, maxVariance);
525}
526
527template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
528inline uint32_t PointDetector::PointPattern::determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t* firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance) const
529{
530 ocean_assert(isValid());
531 ocean_assert(firstSurroundingPixel != nullptr);
532
533 static_assert(tMinCenterColorFixed < tMaxSurroundingColorFixed);
534
535 if (centerPixelValue < tMinCenterColorFixed) // the center pixel should have a certain amount of brightness
536 {
537 return 0u;
538 }
539
540 ocean_assert(int32_t(centerPixelValue) - int32_t(minDifference) >= 0);
541 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
542
543 uint32_t sumSqrDifferences = 0u;
544
545 const uint8_t* surroundingPixel = firstSurroundingPixel;
546
547 VarianceT<uint32_t> variance;
548
549 for (const Index32& positiveOffset : positiveOffsets_)
550 {
551 surroundingPixel += positiveOffset;
552
553 const uint8_t surroundingPixelValue = *surroundingPixel;
554
555 if (surroundingPixelValue > maxSurroundingColor)
556 {
557 return 0u;
558 }
559
560 variance.add(uint32_t(surroundingPixelValue));
561
562 ocean_assert(surroundingPixelValue < centerPixelValue);
563
564 const uint32_t difference = centerPixelValue - surroundingPixelValue;
565
566 sumSqrDifferences += difference * difference;
567 }
568
569 if (sumSqrDifferences != 0u && (maxVariance == 0u || variance.variance() <= maxVariance))
570 {
571 return sumSqrDifferences;
572 }
573
574 return 0u;
575}
576
577template <uint8_t tMinCenterColorFixed, uint8_t tMaxSurroundingColorFixed>
578inline uint32_t PointDetector::PointPattern::determineBrightPointStrength(const uint8_t* yPoint, const unsigned int minDifference, const unsigned int maxVariance) const
579{
580 ocean_assert(yPoint != nullptr);
581
582 const uint8_t centerPixelValue = *yPoint;
583
584 return determineBrightPointStrength<tMinCenterColorFixed, tMaxSurroundingColorFixed>(centerPixelValue, yPoint - negativeOffset_, minDifference, maxVariance);
585}
586
588{
589 ocean_assert(radius_ == 0u || innerRadius_ < radius_);
590 ocean_assert(radius_ == 0u || frameStrideElements_ != 0u);
591
592 return radius_ >= 1u;
593}
594
595template <unsigned int tNumber, bool tMatchSign>
596void PointDetector::closestPoints(const Geometry::SpatialDistribution::DistributionArray& pointsDistributionArray, const size_t queryPointIndex, const Points& points, IndexDistancePairs<tNumber>& indexDistancePairs, const Scalar maxSqrDistance)
597{
598 static_assert(tNumber >= 1u, "Invalid number of points!");
599
600 ocean_assert(indexDistancePairs.empty());
601 ocean_assert(queryPointIndex < points.size());
602
603 const Vector2& point = points[queryPointIndex].observation();
604
605 const unsigned int xBinCenter = pointsDistributionArray.horizontalBin(point.x());
606 const unsigned int yBinCenter = pointsDistributionArray.verticalBin(point.y());
607
608 for (unsigned int xBin = (unsigned int)(std::max(0, int(xBinCenter) - 1)); xBin < std::min(xBinCenter + 2u, pointsDistributionArray.horizontalBins()); ++xBin)
609 {
610 for (unsigned int yBin = (unsigned int)(std::max(0, int(yBinCenter) - 1)); yBin < std::min(yBinCenter + 2u, pointsDistributionArray.verticalBins()); ++yBin)
611 {
612 const Indices32& indices = pointsDistributionArray(xBin, yBin);
613
614 for (const Index32& index : indices)
615 {
616 if (index == Index32(queryPointIndex))
617 {
618 continue;
619 }
620
621 if constexpr (tMatchSign)
622 {
623 if (points[queryPointIndex].sign() != points[index].sign())
624 {
625 continue;
626 }
627 }
628
629 const Scalar sqrDistance = point.sqrDistance(points[index].observation());
630
631 if (sqrDistance > maxSqrDistance)
632 {
633 continue;
634 }
635
636 bool inserted = false;
637
638 if (!indexDistancePairs.empty() && sqrDistance < indexDistancePairs.back().second)
639 {
640 for (size_t nCandidate = 0; nCandidate < indexDistancePairs.size(); ++nCandidate)
641 {
642 if (sqrDistance < indexDistancePairs[nCandidate].second)
643 {
644 if (indexDistancePairs.size() != tNumber)
645 {
646 indexDistancePairs.weakResize(indexDistancePairs.size() + 1);
647 }
648
649 for (size_t n = indexDistancePairs.size() - 1; n > nCandidate; --n)
650 {
651 indexDistancePairs[n] = indexDistancePairs[n - 1];
652 }
653
654 indexDistancePairs[nCandidate] = IndexDistancePair(index, sqrDistance);
655
656 inserted = true;
657 break;
658
659 }
660 }
661 }
662
663 if (!inserted && indexDistancePairs.size() < tNumber)
664 {
665 indexDistancePairs.pushBack(IndexDistancePair(index, sqrDistance));
666 }
667 }
668 }
669 }
670}
671
672inline const Points& PointDetector::points() const
673{
674 return points_;
675}
676
681
682}
683
684}
685
686}
687
688#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:182
uint32_t determineDarkPointStrength(const uint8_t centerPixelValue, const uint8_t *firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance=0u) const
TODO
Definition PointDetector.h:468
CV::PixelPositionsI offsets_
The offsets of this pattern for all surrounding pixels.
Definition PointDetector.h:203
const Indices32 & positiveOffsets() const
Returns the positive offsets for all surrounding pixels starting at the top-left pixel,...
Definition PointDetector.h:450
Indices32 positiveOffsets_
The positive offsets for all surrounding pixels starting at the top-left pixel, all in relation to th...
Definition PointDetector.h:197
float normalizedStrength(const unsigned int strength) const
Returns the normalized strength of a determined strength for this pattern.
Definition PointDetector.h:460
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:419
unsigned int diameter() const
Returns the diameter of the point this pattern is able to detect.
Definition PointDetector.h:424
unsigned int negativeOffset() const
Returns the negative offset for the most top-left pixel of the surrounding pixels.
Definition PointDetector.h:445
bool isValid() const
Returns whether this pattern is valid.
Definition PointDetector.h:587
unsigned int frameStrideElements() const
Returns the stride of the frame which which this pattern has been created.
Definition PointDetector.h:435
uint32_t determineBrightPointStrength(const uint8_t centerPixelValue, const uint8_t *firstSurroundingPixel, const unsigned int minDifference, const unsigned int maxVariance=0u) const
TODO
Definition PointDetector.h:528
unsigned int innerRadius() const
Returns the inner radius of this pattern.
Definition PointDetector.h:430
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 determinePointStrength(const Frame &yFrame, const CV::PixelPosition &observation, int32_t &strength, bool &strict) const
TODO
bool isCircle() const
Returns whether the outer shape of this pattern is a circle or a rectangle.
Definition PointDetector.h:440
const CV::PixelPositionsI & offsets() const
Returns the 2D offsets for all surrounding pixels.
Definition PointDetector.h:455
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
TODO
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:209
Points points_
The precise points detected in the latest frame.
Definition PointDetector.h:407
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:404
Geometry::SpatialDistribution::DistributionArray pointsDistributionArray_
The spatial distribution array of the points detected in the latest frame.
Definition PointDetector.h:410
std::pair< Index32, Scalar > IndexDistancePair
Definition of a pair combining an index with a distance.
Definition PointDetector.h:214
Frame yPointPatternImages_
The frame with all images of point pattern with individual radii.
Definition PointDetector.h:413
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 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::NonMaximumSuppression< uint32_t > &nonMaximumSuppression, Worker *worker=nullptr)
TODO
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.
const Geometry::SpatialDistribution::DistributionArray & pointsDistributionArray() const
Returns the spatial distribution array of the points detected in the latest frame.
Definition PointDetector.h:677
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)
TODO
const Points & points() const
Returns the points detected in the latest frame.
Definition PointDetector.h:672
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::NonMaximumSuppression< uint32_t > *nonMaximumSuppression, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows)
TODO
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:401
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:596
This class implements the possibility to find local maximum in a 2D array by applying a non-maximum-s...
Definition NonMaximumSuppression.h:42
This class implements Ocean's image class.
Definition Frame.h:1808
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:340
void weakResize(const size_t size)
Resizes this vector.
Definition StaticVector.h:534
bool empty() const
Returns whether this vector hold no element.
Definition StaticVector.h:487
void pushBack(const T &value)
Adds a new element to this vector.
Definition StaticVector.h:352
const T & back() const
Returns the last elements of this vector.
Definition StaticVector.h:471
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:1113
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