8 #ifndef META_OCEAN_CV_SEGMENTATION_PIXEL_CONTOUR_H
9 #define META_OCEAN_CV_SEGMENTATION_PIXEL_CONTOUR_H
25 namespace Segmentation
29 template <
typename T>
class PixelContourT;
175 inline unsigned int area()
const;
315 explicit inline operator bool()
const;
342 template <
typename T>
344 contourMostLeftIndex(size_t(-1)),
345 contourCounterClockwise((unsigned int)(-1))
350 template <
typename T>
352 contourPixels(contour.contourPixels),
353 contourMostLeftIndex(contour.contourMostLeftIndex),
354 contourCounterClockwise(contour.contourCounterClockwise),
355 contourBoundingBox(contour.contourBoundingBox)
360 template <
typename T>
362 contourPixels(std::move(contour.contourPixels)),
363 contourMostLeftIndex(contour.contourMostLeftIndex),
364 contourCounterClockwise(contour.contourCounterClockwise),
365 contourBoundingBox(contour.contourBoundingBox)
367 contour.contourMostLeftIndex = (size_t)(-1);
368 contour.contourCounterClockwise = (
unsigned int)(-1);
372 template <
typename T>
374 contourPixels(pixelPositions),
375 contourMostLeftIndex((size_t)(-1)),
376 contourCounterClockwise((unsigned int)(-1)),
377 contourBoundingBox(pixelBoundingBox)
382 template <
typename T>
384 contourPixels(std::move(pixelPositions)),
385 contourMostLeftIndex((size_t)(-1)),
386 contourCounterClockwise((unsigned int)(-1)),
387 contourBoundingBox(pixelBoundingBox)
392 template <
typename T>
394 contourPixels(pixelPositions),
395 contourMostLeftIndex(indexMostLeftPosition),
396 contourCounterClockwise(isCounterClockwise),
397 contourBoundingBox(pixelBoundingBox)
402 template <
typename T>
404 contourPixels(std::move(pixelPositions)),
405 contourMostLeftIndex(indexMostLeftPosition),
406 contourCounterClockwise(isCounterClockwise),
407 contourBoundingBox(pixelBoundingBox)
412 template <
typename T>
414 contourPixels(pixelPositions),
415 contourMostLeftIndex((size_t)(-1)),
416 contourCounterClockwise((unsigned int)(-1)),
417 contourBoundingBox(pixelBoundingBox)
419 if (createSimplified)
421 else if (createDistinct)
427 template <
typename T>
429 contourMostLeftIndex((size_t)(-1)),
430 contourCounterClockwise((unsigned int)(-1))
432 ocean_assert(pixelPositions.size() >= 1);
433 ocean_assert(minimalSqrDistance >= 1u);
434 ocean_assert(startIndex < pixelPositions.size());
442 for (
size_t n = startIndex + 1; n <= startIndex + pixelPositions.size(); ++n)
444 const size_t nModulo = (size_t)
modulo((
int)n, (int)pixelPositions.size());
446 if (
contourPixels.back().sqrDistance(pixelPositions[nModulo]) >= minimalSqrDistance)
456 template <
typename T>
459 return contourPixels;
462 template <
typename T>
465 return contourPixels.size();
468 template <
typename T>
471 return contourPixels.empty();
474 template <
typename T>
477 ocean_assert(index < contourPixels.size());
478 return contourPixels[index];
481 template <
typename T>
492 template <
typename T>
495 if (
this != &contour)
497 contourPixels = std::move(contour.contourPixels);
498 contourMostLeftIndex = contour.contourMostLeftIndex;
499 contourCounterClockwise = contour.contourCounterClockwise;
500 contourBoundingBox = contour.contourBoundingBox;
502 contour.contourMostLeftIndex = (size_t)(-1);
503 contour.contourCounterClockwise = (
unsigned int)(-1);
510 template <
typename T>
513 if (!contourBoundingBox)
516 return contourBoundingBox;
519 template <
typename T>
522 return (
unsigned int)std::abs(areaSigned());
525 template <
typename T>
528 if (contourPixels.size() < 3)
535 for (
size_t i = 0; i < (contourPixels.size() - 1); ++i)
537 const int partialArea = contourPixels[i].x() * contourPixels[i + 1].y() - contourPixels[i].y() * contourPixels[i + 1].x();
546 template <
typename T>
549 if (contourMostLeftIndex != (
size_t)(-1))
550 return contourMostLeftIndex;
552 if (contourPixels.empty())
555 if (contourPixels.size() == 1)
563 size_t index = size_t(-1);
565 for (
size_t n = 0u; n < contourPixels.size(); ++n)
567 if (contourPixels[n].x() < left || (contourPixels[n].x() == left && contourPixels[n].y() > bottom))
569 left = contourPixels[n].x();
570 bottom = contourPixels[n].y();
575 ocean_assert(index !=
size_t(-1));
576 ocean_assert(!contourBoundingBox || left == contourBoundingBox.left());
578 contourMostLeftIndex = index;
582 template <
typename T>
585 if (contourCounterClockwise != (
unsigned int)(-1))
586 return contourCounterClockwise == 1u;
588 const size_t index0 = size_t(indexLeftPosition());
589 ocean_assert(index0 !=
size_t(-1));
591 const size_t index2 =
modulo(
int(index0) - 1,
int(contourPixels.size()));
596 const int dx02 = int(position2.x()) - int(position0.x());
597 const int dy02 = int(position2.y()) - int(position0.y());
599 size_t index1 = size_t(-1);
604 index1 =
modulo(
int(index0 + offset),
int(contourPixels.size()));
607 if (index1 == index2 || index1 == index0)
612 const int dx01 = int(position1.x()) - int(position0.x());
613 const int dy01 = int(position1.y()) - int(position0.y());
616 const int crossProduct = dx01 * dy02 - dx02 * dy01;
618 if (crossProduct != 0)
620 contourCounterClockwise = crossProduct < 0;
621 return contourCounterClockwise == 1u;
627 ocean_assert(
false &&
"This should never happen!");
628 contourCounterClockwise = 1u;
632 template <
typename T>
635 if (contourPixels.size() <= 1)
638 for (
size_t n = 0; n < contourPixels.size() - 1; ++n)
639 if (contourPixels[n] == contourPixels[n + 1u])
642 return contourPixels.front() != contourPixels.back();
645 template <
typename T>
648 if (contourPixels.size() <= 1)
651 for (
size_t n = 1; n < contourPixels.size(); ++n)
652 if (!contourPixels[n - 1].isNeighbor8(contourPixels[n]))
655 return contourPixels.back().isNeighbor8(contourPixels.front());
658 template <
typename T>
661 if (contourPixels.size() <= 1)
664 for (
size_t n = 1; n < contourPixels.size(); ++n)
665 if (!contourPixels[n - 1].isNeighbor4(contourPixels[n]))
668 return contourPixels.back().isNeighbor4(contourPixels.front());
671 template <
typename T>
674 if (contourPixels.size() <= 2)
677 PixelPosition previousOffset(contourPixels[1] - contourPixels[0]);
679 for (
size_t n = 2; n < contourPixels.size(); ++n)
681 const PixelPosition currentOffset(contourPixels[n] - contourPixels[n - 1]);
683 if (currentOffset == previousOffset)
686 previousOffset = currentOffset;
690 PixelPosition currentOffset(contourPixels[0] - contourPixels[contourPixels.size() - 1]);
691 if (previousOffset == currentOffset)
695 if (
PixelPosition(contourPixels[1] - contourPixels[0]) == currentOffset)
701 template <
typename T>
704 if (contourPixels.size() > 1)
707 distinctPixels.reserve(contourPixels.size());
709 distinctPixels.push_back(contourPixels.front());
711 for (
size_t n = 1; n < contourPixels.size(); ++n)
712 if (contourPixels[n - 1] != contourPixels[n])
713 distinctPixels.push_back(contourPixels[n]);
715 if (distinctPixels.size() > 1 && distinctPixels.front() == distinctPixels.back())
716 distinctPixels.pop_back();
718 ocean_assert(distinctPixels.size() <= 1 || distinctPixels.front() != distinctPixels.back());
721 ocean_assert(!contourBoundingBox || contourBoundingBox ==
PixelBoundingBox(distinctPixels));
723 contourMostLeftIndex = size_t(-1);
724 contourCounterClockwise = (
unsigned int)(-1);
726 contourPixels = std::move(distinctPixels);
730 template <
typename T>
733 if (contourPixels.size() > 1)
736 newPositions.reserve(contourPixels.size() * 20);
738 for (
size_t n = 0; n < contourPixels.size(); ++n)
743 int x = int(start.x());
744 int y = int(start.y());
745 const int xEnd = int(end.x());
746 const int yEnd = int(end.y());
750 while (x != xEnd || y != yEnd)
757 contourPixels = std::move(newPositions);
758 ocean_assert(!contourBoundingBox || contourBoundingBox ==
PixelBoundingBox(contourPixels));
760 contourMostLeftIndex = size_t(-1);
761 contourCounterClockwise = (
unsigned int)(-1);
765 template <
typename T>
768 if (contourPixels.size() <= 1)
772 newPixelPositions.reserve(contourPixels.size());
774 VectorI2 currentDirection =
VectorI2(
int(contourPixels.front().x() - contourPixels.back().x()),
int(contourPixels.front().y() - contourPixels.back().y()));
776 for (
size_t n = 1; n < contourPixels.size(); ++n)
778 const VectorI2 newDirection =
VectorI2(
int(contourPixels[n].x() - contourPixels[n - 1].x()),
int(contourPixels[n].y() - contourPixels[n - 1].y()));
780 if (!newDirection.
isNull())
782 if (!similar(currentDirection, newDirection))
784 currentDirection = newDirection;
785 newPixelPositions.push_back(contourPixels[n - 1]);
790 const VectorI2 newDirection =
VectorI2(
int(contourPixels.front().x() - contourPixels.back().x()),
int(contourPixels.front().y() - contourPixels.back().y()));
792 if (currentDirection != newDirection)
793 newPixelPositions.push_back(contourPixels.back());
797 ocean_assert(!newPixelPositions.empty());
800 ocean_assert(debugContour.
boundingBox() == boundingBox());
811 template <
typename T>
814 *
this = simplified();
817 template <
typename T>
820 ocean_assert(contourPixels.size() >= 1);
822 if (contourPixels.empty())
825 ocean_assert(minimalSqrDistance >= 1u);
826 ocean_assert(startIndex < contourPixels.size());
831 template <
typename T>
834 ocean_assert(!contourPixels.empty());
836 unsigned int sqrDistance = contourPixels.front().sqrDistance(contourPixels.back());
838 for (
size_t n = 1; n < contourPixels.size(); ++n)
840 const unsigned int localSqrDistance = contourPixels[n - 1].sqrDistance(contourPixels[n]);
849 template <
typename T>
852 ocean_assert(!contourPixels.empty());
854 unsigned int sqrDistance = contourPixels.front().sqrDistance(contourPixels.back());
856 for (
size_t n = 1; n < contourPixels.size(); ++n)
858 const unsigned int localSqrDistance = contourPixels[n - 1].sqrDistance(contourPixels[n]);
867 template <
typename T>
870 return !contourPixels.empty();
873 template <
typename T>
876 ocean_assert(first.
x() != 0 || first.
y() != 0);
877 ocean_assert(second.
x() != 0 || second.
y() != 0);
881 bool fastResult = first.
x() * second.
y() == second.
x() * first.
y()
882 && (0x80000000 & first.
x()) == (0x80000000 & second.
x())
883 && (0x80000000 & first.
y()) == (0x80000000 & second.
y());
891 ocean_assert(fastResult == (vf == vs));
895 return first.
x() * second.
y() == second.
x() * first.
y()
896 && (0x80000000 & first.
x()) == (0x80000000 & second.
x())
897 && (0x80000000 & first.
y()) == (0x80000000 & second.
y());
This class implements bresenham line algorithms.
Definition: Bresenham.h:27
void findNext(int &x, int &y)
Applies one Bresenham step to find the next pixel.
This class implements a 2D bounding box with pixel precision.
Definition: PixelBoundingBox.h:57
This class implements a 2D pixel position with pixel precision.
Definition: PixelPosition.h:65
void simplify()
Simplifies this (dense) contour to a sparse but identical contour.
Definition: PixelContour.h:812
unsigned int smallestSqrDistanceBetweenPixels() const
Returns the smallest square distance between consecutive contour pixels.
Definition: PixelContour.h:832
size_t size() const
Returns the number of pixel positions of this contour.
Definition: PixelContour.h:463
PixelContourT< T > & operator=(PixelContourT< T > &&contour) noexcept
Move operator.
Definition: PixelContour.h:493
void makeDense()
Makes this pixel contour dense.
Definition: PixelContour.h:731
unsigned int largestSqrDistanceBetweenPixels() const
Returns the largest square distance between consecutive contour pixels.
Definition: PixelContour.h:850
PixelPositionT< T > PixelPosition
Definition of a pixel position.
Definition: PixelContour.h:76
PixelPositions contourPixels
Pixel positions of the contour.
Definition: PixelContour.h:330
size_t indexLeftPosition() const
Returns the index of a left most position of this contour with following pixel right to this position...
Definition: PixelContour.h:547
unsigned int contourCounterClockwise
State whether this contour is counter clockwise: -1 undefined, 0 false, 1 true.
Definition: PixelContour.h:336
PixelBoundingBoxT< T > PixelBoundingBox
Definition of a pixel bounding box.
Definition: PixelContour.h:86
void makeDistinct()
Removes non distinct pixels from this contour.
Definition: PixelContour.h:702
bool isEmpty() const
Returns whether this contour does not hold any pixel position.
Definition: PixelContour.h:469
PixelContourT< T > & operator=(const PixelContourT< T > &contour)
Assign operator.
Definition: PixelContour.h:482
size_t contourMostLeftIndex
Index of the most left pixel.
Definition: PixelContour.h:333
const PixelPositions & pixels() const
Returns the pixels of this contour.
Definition: PixelContour.h:457
PixelContourT(PixelPositions &&pixelPositions, const PixelBoundingBox &pixelBoundingBox=PixelBoundingBox())
Creates a new pixel contour object by moving set of pixel positions that represent the pixel location...
Definition: PixelContour.h:383
PixelContourT(PixelContourT< T > &&contour) noexcept
Move constructor.
Definition: PixelContour.h:361
bool isDense() const
Returns whether this contour is dense.
Definition: PixelContour.h:646
bool isDense4() const
Returns whether this contour is dense according to a 4-neighborhood.
Definition: PixelContour.h:659
PixelContourT(const PixelPositions &pixelPositions, const PixelBoundingBox &pixelBoundingBox=PixelBoundingBox())
Creates a new pixel contour object by a given set of pixel positions that represent the pixel locatio...
Definition: PixelContour.h:373
const PixelBoundingBox & boundingBox() const
Returns the bounding box of this contour.
Definition: PixelContour.h:511
bool isDistinct() const
Returns whether all consecutive pixels of this contour are different.
Definition: PixelContour.h:633
PixelContourT(const PixelContourT< T > &contour)
Copy constructor.
Definition: PixelContour.h:351
PixelContourT< T > simplified() const
Returns the simplified contour of this contour which will be a sparse but identical contour.
Definition: PixelContour.h:766
unsigned int area() const
Computes the area of a contour Uses the Shoelace formula to determine the area of a contour.
Definition: PixelContour.h:520
PixelContourT(const PixelPositions &pixelPositions, const size_t indexMostLeftPosition, const bool isCounterClockwise, const PixelBoundingBox &pixelBoundingBox=PixelBoundingBox())
Creates a new pixel contour object by a given set of pixel positions that represent the pixel locatio...
Definition: PixelContour.h:393
PixelContourT(const PixelPositions &pixelPositions, const unsigned int minimalSqrDistance, const size_t startIndex=0)
Creates a new sparse pixel contour object by a given set of pixel positions that represent the pixel ...
Definition: PixelContour.h:428
PixelContourT()
Creates a new pixel contour object.
Definition: PixelContour.h:343
PixelContourT(const bool createDistinct, const bool createSimplified, const PixelPositions &pixelPositions, const PixelBoundingBox &pixelBoundingBox=PixelBoundingBox())
Creates a new pixel contour object by a given set of pixel positions that represent the pixel locatio...
Definition: PixelContour.h:413
std::vector< PixelPosition > PixelPositions
Definition of a vector holding pixel positions.
Definition: PixelContour.h:81
static bool similar(const VectorI2 &first, const VectorI2 &second)
Returns whether two given vectors are parallel and point into the same direction.
Definition: PixelContour.h:874
bool isSimplified() const
Returns whether this contour is simplified.
Definition: PixelContour.h:672
PixelBoundingBox contourBoundingBox
Bounding box of the contour.
Definition: PixelContour.h:339
const PixelPosition & operator[](const size_t index) const
Returns the pixel position of this pixel contour.
Definition: PixelContour.h:475
bool isCounterClockwise() const
Returns whether this contour is defined in a counter clockwise order, clockwise otherwise.
Definition: PixelContour.h:583
PixelContourT(PixelPositions &&pixelPositions, const size_t indexMostLeftPosition, const bool isCounterClockwise, const PixelBoundingBox &pixelBoundingBox=PixelBoundingBox())
Creates a new pixel contour object by moving a set of pixel positions that represent the pixel locati...
Definition: PixelContour.h:403
PixelContourT< T > sparseContour(const unsigned int minimalSqrDistance, const size_t startIndex=0) const
Creates a sparse contour out of this contour by ensuring that the minimal distance between consecutiv...
Definition: PixelContour.h:818
int areaSigned() const
Computes the signed area of a contour Uses the Shoelace formula to determine the area of a contour.
Definition: PixelContour.h:526
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static constexpr T minValue()
Returns the min scalar value.
Definition: Numeric.h:3250
static constexpr T maxValue()
Returns the max scalar value.
Definition: Numeric.h:3244
const T & x() const noexcept
Returns the x value.
Definition: Vector2.h:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
bool isNull() const
Returns whether this vector is a null vector up to a small epsilon.
Definition: Vector2.h:734
bool normalize()
Normalizes this vector.
Definition: Vector2.h:600
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition: base/Utilities.h:1089
T modulo(const T &value, const T &ring)
Returns the modulo value of a given parameter within a ring allowing positive and negative parameters...
Definition: base/Utilities.h:924
PixelPositionT< unsigned int > PixelPosition
Definition of the default PixelPosition object with a data type allowing only positive coordinate val...
Definition: PixelPosition.h:27
PixelBoundingBoxT< unsigned int > PixelBoundingBox
Definition of the default PixelBoundingBox object with data type allowing only positive coordinate va...
Definition: PixelBoundingBox.h:21
std::vector< PixelContourI > PixelContoursI
Definition of a vector holding pixel contours (with positive and negative coordinate values).
Definition: PixelContour.h:57
PixelContourT< unsigned int > PixelContour
Definition of the default PixelContour object with a data type allowing only positive coordinate valu...
Definition: PixelContour.h:29
std::vector< PixelContour > PixelContours
Definition of a vector holding pixel contours (with positive coordinate values).
Definition: PixelContour.h:50
PixelContourT< int > PixelContourI
Definition of a PixelContour object with a data type allowing positive and negative coordinate values...
Definition: PixelContour.h:43
VectorT2< int > VectorI2
Definition of a 2D vector with integer values.
Definition: Vector2.h:49
float Scalar
Definition of a scalar type.
Definition: Math.h:128
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15