8 #ifndef META_OCEAN_CV_NON_MAXIMUM_SUPPRESSION_H
9 #define META_OCEAN_CV_NON_MAXIMUM_SUPPRESSION_H
49 template <
typename TCoordinate,
typename TStrength>
71 inline const TStrength&
strength()
const;
80 template <
bool tLeftLargerThanRight = true>
92 template <
typename TCoordinate,
typename TStrength>
105 template <
typename TCoordinate,
typename TStrength>
133 inline unsigned int x()
const;
186 inline unsigned int width()
const;
192 inline unsigned int height()
const;
198 inline unsigned int yOffset()
const;
208 inline void addCandidate(
const unsigned int x,
const unsigned int y,
const T& strength);
223 void addCandidates(
const T* values,
const unsigned int valuesPaddingElements,
const unsigned int firstColumn,
const unsigned int numberColumns,
const unsigned int firstRow,
const unsigned int numberRows,
const T& minimalThreshold,
Worker* worker);
246 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum = true>
281 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum>
294 template <
typename TFloat>
307 template <
typename TFloat>
323 void addCandidatesSubset(
const T* values,
const unsigned int valuesStrideElements,
const unsigned int firstColumn,
const unsigned int numberColumns,
const T* minimalThreshold,
const unsigned int firstRow,
const unsigned int numberRows);
337 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum>
349 template <
typename T>
350 template <
typename TCoordinate,
typename TStrength>
358 template <
typename T>
359 template <
typename TCoordinate,
typename TStrength>
365 template <
typename T>
366 template <
typename TCoordinate,
typename TStrength>
367 template <
bool tLeftLargerThanRight>
370 if constexpr (tLeftLargerThanRight)
380 template <
typename T>
388 template <
typename T>
396 template <
typename T>
402 template <
typename T>
408 template <
typename T>
411 *
this = std::move(nonMaximumSuppression);
414 template <
typename T>
416 width_(nonMaximumSuppression.width_),
417 rows_(nonMaximumSuppression.rows_)
422 template <
typename T>
430 template <
typename T>
436 template <
typename T>
442 template <
typename T>
450 template <
typename T>
457 if (
rows_[y].empty())
459 rows_[y].reserve(128);
462 rows_[y].emplace_back(x, strength);
465 template <
typename T>
466 void NonMaximumSuppression<T>::addCandidates(
const T* values,
const unsigned int valuesPaddingElements,
const unsigned int firstColumn,
const unsigned int numberColumns,
const unsigned int firstRow,
const unsigned int numberRows,
const T& minimalThreshold,
Worker* worker)
468 ocean_assert(values !=
nullptr);
470 ocean_assert(firstColumn + numberColumns <=
width_);
474 const unsigned int valuesStrideElements =
width_ + valuesPaddingElements;
478 worker->
executeFunction(
Worker::Function::create(*
this, &
NonMaximumSuppression<T>::addCandidatesSubset, values, valuesStrideElements, firstColumn, numberColumns, &minimalThreshold, 0u, 0u), firstRow, numberRows, 5u, 6u, 20u);
482 addCandidatesSubset(values, valuesStrideElements, firstColumn, numberColumns, &minimalThreshold, firstRow, numberRows);
486 template <
typename T>
493 while (!suppressionRow.empty())
495 if (suppressionRow.back().x() >= x)
497 suppressionRow.pop_back();
506 template <
typename T>
507 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum>
510 ocean_assert(firstColumn + numberColumns <=
width_);
519 worker->
executeFunction(
Worker::Function::create(*
this, &
NonMaximumSuppression<T>::suppressNonMaximumSubset<TCoordinate, TStrength, tStrictMaximum>, &result, firstColumn, numberColumns, &lock, positionCallback, 0u, 0u), firstRow, numberRows, 5u, 6u, 3u);
523 suppressNonMaximumSubset<TCoordinate, TStrength, tStrictMaximum>(&result, firstColumn, numberColumns,
nullptr, positionCallback, firstRow, numberRows);
529 template <
typename T>
538 template <
typename T>
541 if (
this != &nonMaximumSuppression)
543 width_ = nonMaximumSuppression.width_;
544 nonMaximumSuppression.width_ = 0u;
546 rows_ = std::move(nonMaximumSuppression.rows_);
552 template <
typename T>
555 if (
this != &nonMaximumSuppression)
564 template <
typename T>
565 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum>
569 ocean_assert(radius >= TCoordinate(1));
573 const unsigned int horizontalBins = std::max(1u, (
width + binSize - 1u) / binSize);
574 const unsigned int verticalBins = std::max(1u, (
height + binSize - 1u) / binSize);
576 ocean_assert(binSize * horizontalBins >=
width);
577 ocean_assert(binSize * verticalBins >=
height);
583 for (
size_t n = 0; n < strengthPositions.size(); ++n)
587 ocean_assert((
unsigned int)(position.
x()) <
width);
588 ocean_assert((
unsigned int)(position.
y()) <
height);
590 const unsigned int xBin = (
unsigned int)(position.
x()) / binSize;
591 const unsigned int yBin = (
unsigned int)(position.
y()) / binSize;
593 ocean_assert(xBin <= horizontalBins);
594 ocean_assert(yBin <= verticalBins);
596 indexGroups[yBin * horizontalBins + xBin].emplace_back(
Index32(n));
599 std::vector<uint8_t> validPositions(strengthPositions.size(), 1u);
601 const TCoordinate sqrRadius = radius * radius;
603 for (
size_t nCandidate = 0; nCandidate < strengthPositions.size(); ++nCandidate)
605 if (validPositions[nCandidate] == 0u)
613 const unsigned int xCandidateBin = (
unsigned int)(candidatePosition.
x()) / binSize;
614 const unsigned int yCandidateBin = (
unsigned int)(candidatePosition.
y()) / binSize;
616 ocean_assert(xCandidateBin <= horizontalBins);
617 ocean_assert(yCandidateBin <= verticalBins);
619 bool checkNextCandidate =
false;
621 for (
unsigned int yBin = (
unsigned int)(max(0,
int(yCandidateBin) - 1)); !checkNextCandidate && yBin < min(yCandidateBin + 2u, verticalBins); ++yBin)
623 for (
unsigned int xBin = (
unsigned int)(max(0,
int(xCandidateBin) - 1)); !checkNextCandidate && xBin < min(xCandidateBin + 2u, horizontalBins); ++xBin)
625 const Indices32& indices = indexGroups[yBin * horizontalBins + xBin];
627 for (
const Index32& nTest : indices)
629 if (nTest ==
Index32(nCandidate))
638 if (candidatePosition.
sqrDistance(testPosition) <= sqrRadius)
642 validPositions[nTest] = 0u;
646 validPositions[nCandidate] = 0u;
648 checkNextCandidate =
true;
655 if constexpr (tStrictMaximum)
659 validPositions[nCandidate] = 0u;
660 validPositions[nTest] = 0u;
662 checkNextCandidate =
true;
669 if (candidatePosition.
y() < testPosition.
y() || (candidatePosition.
y() == testPosition.
y() && candidatePosition.
x() < testPosition.
x()))
673 validPositions[nCandidate] = 0u;
675 checkNextCandidate =
true;
680 ocean_assert(testPosition.
y() < candidatePosition.
y() || (testPosition.
y() == candidatePosition.
y() && testPosition.
x() < candidatePosition.
x()));
684 validPositions[nTest] = 0u;
695 remainingPositions.reserve(strengthPositions.size());
699 ocean_assert(validIndices->empty());
701 validIndices->clear();
702 validIndices->reserve(strengthPositions.size());
704 for (
size_t n = 0; n < validPositions.size(); ++n)
706 if (validPositions[n])
708 remainingPositions.emplace_back(strengthPositions[n]);
709 validIndices->emplace_back(
Index32(n));
715 for (
size_t n = 0; n < validPositions.size(); ++n)
717 if (validPositions[n])
719 remainingPositions.emplace_back(strengthPositions[n]);
724 return remainingPositions;
727 template <
typename T>
728 template <
typename TFloat>
731 static_assert(std::is_floating_point<TFloat>::value,
"Invalid floating point data type!");
744 const TFloat df = (TFloat(rightValue) - TFloat(leftValue)) * TFloat(0.5);
747 const TFloat dff = TFloat(leftValue) + TFloat(rightValue) - TFloat(middleValue) * TFloat(2);
751 location = TFloat(0);
755 const TFloat x = -df / dff;
757 if (x < TFloat(-1) || x > TFloat(1))
766 template <
typename T>
767 template <
typename TFloat>
770 static_assert(std::is_floating_point<TFloat>::value,
"Invalid floating point data type!");
772 const T& value00 = topValues[0];
773 const T& value01 = topValues[1];
774 const T& value02 = topValues[2];
776 const T& value10 = centerValues[0];
777 const T& value11 = centerValues[1];
778 const T& value12 = centerValues[2];
780 const T& value20 = bottomValues[0];
781 const T& value21 = bottomValues[1];
782 const T& value22 = bottomValues[2];
786 ocean_assert(value11 >= value00 && value11 >= value01 && value11 >= value02);
787 ocean_assert(value11 >= value10 && value11 >= value12);
788 ocean_assert(value11 >= value20 && value11 >= value21 && value11 >= value22);
792 const TFloat dx = TFloat(value12 - value10) * TFloat(0.5);
793 const TFloat dy = TFloat(value21 - value01) * TFloat(0.5);
796 const TFloat dxx = TFloat(value12 + value10 - value11 * TFloat(2));
797 const TFloat dyy = TFloat(value21 + value01 - value11 * TFloat(2));
803 const TFloat dxy = TFloat(value22 + value00 - value20 - value02) * TFloat(0.25);
805 const TFloat denominator = dxx * dyy - dxy * dxy;
813 const TFloat factor = TFloat(1) / denominator;
815 const TFloat offsetX = -(dyy * dx - dxy * dy) * factor;
816 const TFloat offsetY = -(dxx * dy - dxy * dx) * factor;
818 if (offsetX < TFloat(-1) || offsetX > TFloat(1) || offsetY < TFloat(-1) || offsetY > TFloat(1))
827 template <
typename T>
828 void NonMaximumSuppression<T>::addCandidatesSubset(
const T* values,
const unsigned int valuesStrideElements,
const unsigned int firstColumn,
const unsigned int numberColumns,
const T* minimalThreshold,
const unsigned int firstRow,
const unsigned int numberRows)
830 ocean_assert(values !=
nullptr);
831 ocean_assert(valuesStrideElements >=
width_);
832 ocean_assert(firstColumn + numberColumns <=
width_);
837 const T localThreshold = *minimalThreshold;
839 values += firstRow * valuesStrideElements;
841 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
843 for (
unsigned int x = firstColumn; x < firstColumn + numberColumns; ++x)
845 if (values[x] >= localThreshold)
851 values += valuesStrideElements;
855 template <
typename T>
856 template <
typename TCoordinate,
typename TStrength,
bool tStrictMaximum>
859 ocean_assert(strengthPositions);
861 ocean_assert(firstColumn + numberColumns <=
width_);
863 ocean_assert(firstRow + numberRows <= (
unsigned int)
rows_.
endIndex());
865 if (numberColumns < 3u || numberRows < 3u)
870 const unsigned int firstCenterColumn = max(1u, firstColumn);
871 const unsigned int endCenterColumn = min(firstColumn + numberColumns,
width_ - 1u);
873 const unsigned int firstCenterRow = max((
unsigned int)
rows_.
firstIndex() + 1u, firstRow);
874 const unsigned int endCenterRow = min(firstRow + numberRows, (
unsigned int)
rows_.
lastIndex());
876 ocean_assert(firstCenterRow >= 1u);
879 localStrengthPositions.reserve(100);
881 for (
unsigned int y = firstCenterRow; y < endCenterRow; ++y)
887 typename StrengthCandidateRow::const_iterator i0 = row0.
begin();
888 typename StrengthCandidateRow::const_iterator i2 = row2.begin();
890 typename StrengthCandidateRow::const_iterator i1Minus = row1.end();
891 typename StrengthCandidateRow::const_iterator i1Plus = row1.size() > 1 ? row1.begin() + 1 : row1.end();
893 for (
typename StrengthCandidateRow::const_iterator i1 = row1.begin(); i1 != row1.end(); ++i1)
895 ocean_assert(i1->x() >= 0u && i1->x() + 1u <=
width_);
898 if (i1->x() >= firstCenterColumn && i1->x() < endCenterColumn && (i1Minus == row1.end() || i1Minus->x() + 1u != i1->x() || (tStrictMaximum && i1Minus->strength() < i1->strength()) || (!tStrictMaximum && i1Minus->strength() <= i1->strength())))
901 if (i1Plus == row1.end() || i1Plus->x() != i1->x() + 1u || i1Plus->strength() < i1->strength())
904 while (i0 != row0.end())
906 if (i0->x() + 1u < i1->x())
917 ocean_assert(i0 == row0.end() || i0->x() + 1u >= i1->x());
919 if (i0 != row0.end() && i0->x() <= i1->x() + 1u)
921 ocean_assert(i0->x() + 1u == i1->x() || i0->x() == i1->x() || i0->x() - 1u == i1->x());
923 if ((tStrictMaximum && i0->strength() >= i1->strength()) || (!tStrictMaximum && i0->strength() > i1->strength()))
930 const typename StrengthCandidateRow::const_iterator i0Plus = i0 + 1;
932 if (i0Plus != row0.end() && i0Plus->x() <= i1->x() + 1u)
934 if ((tStrictMaximum && i0Plus->strength() >= i1->strength()) || (!tStrictMaximum && i0Plus->strength() > i1->strength()))
941 const typename StrengthCandidateRow::const_iterator i0PlusPlus = i0Plus + 1;
943 if (i0PlusPlus != row0.end() && i0PlusPlus->x() <= i1->x() + 1u)
945 ocean_assert(i0PlusPlus->x() == i1->x() + 1u);
947 if ((tStrictMaximum && i0PlusPlus->strength() >= i1->strength()) || (!tStrictMaximum && i0PlusPlus->strength() > i1->strength()))
957 while (i2 != row2.end())
959 if (i2->x() + 1u < i1->x())
970 ocean_assert(i2 == row2.end() || i2->x() + 1u >= i1->x());
972 if (i2 != row2.end() && i2->x() <= i1->x() + 1u)
974 ocean_assert(i2->x() + 1u == i1->x() || i2->x() == i1->x() || i2->x() - 1u == i1->x());
976 if (i2->x() + 1u == i1->x())
980 if ((tStrictMaximum && i2->strength() >= i1->strength()) || (!tStrictMaximum && i2->strength() > i1->strength()))
987 if (i2->strength() >= i1->strength())
995 const typename StrengthCandidateRow::const_iterator i2Plus = i2 + 1;
997 if (i2Plus != row2.end() && i2Plus->x() <= i1->x() + 1u)
999 if (i2Plus->strength() >= i1->strength())
1004 const typename StrengthCandidateRow::const_iterator i2PlusPlus = i2Plus + 1;
1006 if (i2PlusPlus != row2.end() && i2PlusPlus->x() <= i1->x() + 1u)
1008 ocean_assert(i2PlusPlus->x() == i1->x() + 1u);
1010 if (i2PlusPlus->strength() >= i1->strength())
1016 if (positionCallback)
1018 TCoordinate preciseX, preciseY;
1019 TStrength preciseStrength;
1020 if ((*positionCallback)(i1->x(), y, i1->strength(), preciseX, preciseY, preciseStrength))
1022 localStrengthPositions.emplace_back(preciseX, preciseY, preciseStrength);
1027 localStrengthPositions.emplace_back(TCoordinate(i1->x()), TCoordinate(y), i1->strength());
1036 if (i1Plus != row1.end())
1043 strengthPositions->insert(strengthPositions->end(), localStrengthPositions.begin(), localStrengthPositions.end());
This class holds the horizontal position and strength parameter of an interest pixel.
Definition: NonMaximumSuppression.h:114
StrengthCandidate()
Creates a new candidate object.
Definition: NonMaximumSuppression.h:381
const T & strength() const
Returns the strength parameter of this object.
Definition: NonMaximumSuppression.h:403
unsigned int x() const
Returns the horizontal position of this candidate object.
Definition: NonMaximumSuppression.h:397
T strength_
Strength parameter of this object.
Definition: NonMaximumSuppression.h:147
unsigned int positionX_
Horizontal position of this object.
Definition: NonMaximumSuppression.h:144
This class extends a 2D position by a third parameter storing a strength value.
Definition: NonMaximumSuppression.h:51
static bool compareStrength(const StrengthPosition< TCoordinate, TStrength > &left, const StrengthPosition< TCoordinate, TStrength > &right)
Compares the strength value of two objects.
Definition: NonMaximumSuppression.h:368
StrengthPosition()=default
Creates a new object with default strength parameter.
const TStrength & strength() const
Returns the strength parameter of this object.
Definition: NonMaximumSuppression.h:360
TStrength strength_
Strength parameter of this object.
Definition: NonMaximumSuppression.h:86
This class implements the possibility to find local maximum in a 2D array by applying a non-maximum-s...
Definition: NonMaximumSuppression.h:41
NonMaximumSuppression< T > & operator=(NonMaximumSuppression< T > &&nonMaximumSuppression)
Move operator.
Definition: NonMaximumSuppression.h:539
unsigned int width_
Width of this object.
Definition: NonMaximumSuppression.h:343
StrengthCandidateRows rows_
All candidate rows.
Definition: NonMaximumSuppression.h:346
static bool determinePrecisePeakLocation1(const T &leftValue, const T &middleValue, const T &rightValue, TFloat &location)
Determines the precise peak location in 1D space for three discrete neighboring measurements at locat...
Definition: NonMaximumSuppression.h:729
void reset()
Removes the gathered non-maximum suppression information so that this object can be reused again (for...
Definition: NonMaximumSuppression.h:530
unsigned int height() const
Returns the height of this object.
Definition: NonMaximumSuppression.h:437
static StrengthPositions< TCoordinate, TStrength > suppressNonMaximum(const unsigned int width, const unsigned int height, const StrengthPositions< TCoordinate, TStrength > &strengthPositions, const TCoordinate radius, Indices32 *validIndices=nullptr)
Applies a non-maximum-suppression based on already existing strength positions (just with a custom su...
unsigned int yOffset() const
Returns the optional offset in the vertical direction.
Definition: NonMaximumSuppression.h:443
StrengthPositions< TCoordinate, TStrength > suppressNonMaximum(const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows, Worker *worker=nullptr, const PositionCallback< TCoordinate, TStrength > *positionCallback=nullptr) const
Applies a non-maximum-suppression search on a given 2D frame in a 3x3 neighborhood (eight neighbors).
void suppressNonMaximumSubset(StrengthPositions< TCoordinate, TStrength > *strengthPositions, const unsigned int firstColumn, const unsigned int firstRow, Lock *lock, const PositionCallback< TCoordinate, TStrength > *positionCallback, const unsigned int numberColumns, const unsigned int numberRows) const
Applies a non-maximum-suppression search on a subset of a given 2D frame in a 3x3 neighborhood (eight...
Definition: NonMaximumSuppression.h:857
void addCandidatesSubset(const T *values, const unsigned int valuesStrideElements, const unsigned int firstColumn, const unsigned int numberColumns, const T *minimalThreshold, const unsigned int firstRow, const unsigned int numberRows)
Adds new candidates to this object from a subset of a given buffer providing one value for each bin/p...
Definition: NonMaximumSuppression.h:828
void removeCandidatesRightFrom(const unsigned int x, const unsigned int y)
Removes all candidates from a specified row having a horizontal location equal or larger than a speci...
Definition: NonMaximumSuppression.h:487
std::vector< StrengthPosition< TCoordinate, TStrength > > StrengthPositions
Definition of a vector holding strength pixel positions.
Definition: NonMaximumSuppression.h:93
void addCandidate(const unsigned int x, const unsigned int y, const T &strength)
Adds a new candidate to this object.
Definition: NonMaximumSuppression.h:451
static bool determinePrecisePeakLocation2(const T *const topValues, const T *const centerValues, const T *const bottomValues, VectorT2< TFloat > &location)
Determines the precise peak location in 2D space for nine discrete neighboring measurements at locati...
Definition: NonMaximumSuppression.h:768
unsigned int width() const
Returns the width of this object.
Definition: NonMaximumSuppression.h:431
NonMaximumSuppression(NonMaximumSuppression< T > &&nonMaximumSuppression) noexcept
Move constructor.
Definition: NonMaximumSuppression.h:409
void addCandidates(const T *values, const unsigned int valuesPaddingElements, const unsigned int firstColumn, const unsigned int numberColumns, const unsigned int firstRow, const unsigned int numberRows, const T &minimalThreshold, Worker *worker)
Adds new candidates to this object from a given buffer providing one value for each bin/pixel of this...
Definition: NonMaximumSuppression.h:466
ShiftVector< StrengthCandidateRow > StrengthCandidateRows
Definition of a vector holding a vector of strength candidates.
Definition: NonMaximumSuppression.h:158
std::vector< StrengthCandidate > StrengthCandidateRow
Definition of a vector holding strength candidate objects.
Definition: NonMaximumSuppression.h:153
This class implements a container for callback functions.
Definition: Callback.h:3456
static Caller< void > create(CT &object, typename MemberFunctionPointerMaker< CT, void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a member function with no function parameter.
Definition: Caller.h:3023
This class implements a recursive lock object.
Definition: Lock.h:31
This class provides basic numeric functionalities.
Definition: Numeric.h:57
This class implements an optional recursive scoped lock object locking the lock object only if it's d...
Definition: Lock.h:325
bool isValidIndex(const Index index) const
Returns whether a specific index is valid for this vector and matches to the current offset layout.
Definition: ShiftVector.h:646
size_t size() const
Returns the number of elements that are stored by this object.
Definition: ShiftVector.h:490
Index endIndex() const
Returns the index of the element behind the last (excluding) element of this object.
Definition: ShiftVector.h:435
void clear()
Clears this object, the specified index shift will be untouched.
Definition: ShiftVector.h:658
std::ptrdiff_t Index
Definition of an element index.
Definition: ShiftVector.h:38
Iterator begin()
Returns the iterator for the first data element.
Definition: ShiftVector.h:670
Index lastIndex() const
Returns the index of the last (including) element of this object.
Definition: ShiftVector.h:422
Index firstIndex() const
Returns the index of the first element of this object.
Definition: ShiftVector.h:416
This class implements a vector with two elements.
Definition: Vector2.h:96
const TCoordinate & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const TCoordinate & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
T sqrDistance(const VectorT2< T > &right) const
Returns the square distance between this 2D position and a second 2D position.
Definition: Vector2.h:633
This class implements a worker able to distribute function calls over different threads.
Definition: Worker.h:33
bool executeFunction(const Function &function, const unsigned int first, const unsigned int size, const unsigned int firstIndex=(unsigned int)(-1), const unsigned int sizeIndex=(unsigned int)(-1), const unsigned int minimalIterations=1u, const unsigned int threadIndex=(unsigned int)(-1))
Executes a callback function separable by two function parameters.
std::vector< Indices32 > IndexGroups32
Definition of a vector holding 32 bit indices, so we have groups of indices.
Definition: Base.h:102
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
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15