8#ifndef META_OCEAN_CV_SEGMENTATION_PIXEL_CONTOUR_H
9#define META_OCEAN_CV_SEGMENTATION_PIXEL_CONTOUR_H
29template <
typename T>
class PixelContourT;
175 inline unsigned int area()
const;
315 explicit inline operator bool()
const;
344 pixels_(contour.pixels_),
345 mostLeftIndex_(contour.mostLeftIndex_),
346 counterClockwise_(contour.counterClockwise_),
347 boundingBox_(contour.boundingBox_)
354 pixels_(std::move(contour.pixels_)),
355 mostLeftIndex_(contour.mostLeftIndex_),
356 counterClockwise_(contour.counterClockwise_),
357 boundingBox_(contour.boundingBox_)
359 contour.mostLeftIndex_ = (
size_t)(-1);
360 contour.counterClockwise_ = (
unsigned int)(-1);
366 pixels_(pixelPositions),
367 mostLeftIndex_((
size_t)(-1)),
368 counterClockwise_((unsigned int)(-1)),
369 boundingBox_(pixelBoundingBox)
376 pixels_(std::move(pixelPositions)),
377 mostLeftIndex_((
size_t)(-1)),
378 counterClockwise_((unsigned int)(-1)),
379 boundingBox_(pixelBoundingBox)
386 pixels_(pixelPositions),
387 mostLeftIndex_(indexMostLeftPosition),
388 counterClockwise_(isCounterClockwise),
389 boundingBox_(pixelBoundingBox)
396 pixels_(std::move(pixelPositions)),
397 mostLeftIndex_(indexMostLeftPosition),
398 counterClockwise_(isCounterClockwise),
399 boundingBox_(pixelBoundingBox)
406 pixels_(pixelPositions),
407 mostLeftIndex_((
size_t)(-1)),
408 counterClockwise_((unsigned int)(-1)),
409 boundingBox_(pixelBoundingBox)
411 if (createSimplified)
415 else if (createDistinct)
425 mostLeftIndex_((
size_t)(-1)),
426 counterClockwise_((unsigned int)(-1))
428 ocean_assert(pixelPositions.size() >= 1);
429 ocean_assert(minimalSqrDistance >= 1u);
430 ocean_assert(startIndex < pixelPositions.size());
433 pixels_.reserve(pixelPositions.size());
436 pixels_.push_back(pixelPositions[startIndex]);
438 for (
size_t n = startIndex + 1; n <= startIndex + pixelPositions.size(); ++n)
440 const size_t nModulo = (
size_t)
modulo((
int)n, (int)pixelPositions.size());
442 if (
pixels_.back().sqrDistance(pixelPositions[nModulo]) >= minimalSqrDistance)
444 pixels_.push_back(pixelPositions[nModulo]);
465 return pixels_.size();
471 return pixels_.empty();
477 ocean_assert(index < pixels_.size());
478 return pixels_[index];
495 if (
this != &contour)
497 pixels_ = std::move(contour.pixels_);
498 mostLeftIndex_ = contour.mostLeftIndex_;
499 counterClockwise_ = contour.counterClockwise_;
500 boundingBox_ = contour.boundingBox_;
502 contour.mostLeftIndex_ = (
size_t)(-1);
503 contour.counterClockwise_ = (
unsigned int)(-1);
524 return (
unsigned int)std::abs(areaSigned());
530 if (pixels_.size() < 3)
537 for (
size_t i = 0; i < (pixels_.size() - 1); ++i)
539 const int partialArea = pixels_[i].x() * pixels_[i + 1].y() - pixels_[i].y() * pixels_[i + 1].x();
547 const int partialArea = pixels_.back().x() * pixels_.front().y() - pixels_.back().y() * pixels_.front().x();
560 if (mostLeftIndex_ != (
size_t)(-1))
562 return mostLeftIndex_;
570 if (pixels_.size() == 1)
580 size_t index =
size_t(-1);
582 for (
size_t n = 0u; n < pixels_.size(); ++n)
584 if (pixels_[n].x() < left || (pixels_[n].x() == left && pixels_[n].y() > bottom))
586 left = pixels_[n].x();
587 bottom = pixels_[n].y();
592 ocean_assert(index !=
size_t(-1));
593 ocean_assert(!boundingBox_ || left == boundingBox_.left());
595 mostLeftIndex_ = index;
602 if (counterClockwise_ != (
unsigned int)(-1))
604 return counterClockwise_ == 1u;
607 const size_t index0 =
size_t(indexLeftPosition());
608 ocean_assert(index0 !=
size_t(-1));
610 const size_t index2 =
modulo(
int(index0) - 1,
int(pixels_.size()));
615 const int dx02 = int(position2.x()) - int(position0.x());
616 const int dy02 = int(position2.y()) - int(position0.y());
618 size_t index1 =
size_t(-1);
623 index1 =
modulo(
int(index0 + offset),
int(pixels_.size()));
626 if (index1 == index2 || index1 == index0)
633 const int dx01 = int(position1.x()) - int(position0.x());
634 const int dy01 = int(position1.y()) - int(position0.y());
637 const int crossProduct = dx01 * dy02 - dx02 * dy01;
639 if (crossProduct != 0)
641 counterClockwise_ = crossProduct < 0;
642 return counterClockwise_ == 1u;
648 ocean_assert(
false &&
"This should never happen!");
649 counterClockwise_ = 1u;
656 if (pixels_.size() <= 1)
661 for (
size_t n = 0; n < pixels_.size() - 1; ++n)
663 if (pixels_[n] == pixels_[n + 1u])
669 return pixels_.front() != pixels_.back();
675 if (pixels_.size() <= 1)
680 for (
size_t n = 1; n < pixels_.size(); ++n)
682 if (!pixels_[n - 1].isNeighbor8(pixels_[n]))
688 return pixels_.back().isNeighbor8(pixels_.front());
694 if (pixels_.size() <= 1)
699 for (
size_t n = 1; n < pixels_.size(); ++n)
701 if (!pixels_[n - 1].isNeighbor4(pixels_[n]))
707 return pixels_.back().isNeighbor4(pixels_.front());
713 if (pixels_.size() <= 2)
720 for (
size_t n = 2; n < pixels_.size(); ++n)
722 const PixelPosition currentOffset(pixels_[n] - pixels_[n - 1]);
724 if (currentOffset == previousOffset)
729 previousOffset = currentOffset;
733 PixelPosition currentOffset(pixels_[0] - pixels_[pixels_.size() - 1]);
734 if (previousOffset == currentOffset)
751 if (pixels_.size() > 1)
754 distinctPixels.reserve(pixels_.size());
756 distinctPixels.push_back(pixels_.front());
758 for (
size_t n = 1; n < pixels_.size(); ++n)
760 if (pixels_[n - 1] != pixels_[n])
762 distinctPixels.push_back(pixels_[n]);
766 if (distinctPixels.size() > 1 && distinctPixels.front() == distinctPixels.back())
768 distinctPixels.pop_back();
771 ocean_assert(distinctPixels.size() <= 1 || distinctPixels.front() != distinctPixels.back());
774 ocean_assert(!boundingBox_ || boundingBox_ ==
PixelBoundingBox(distinctPixels));
776 mostLeftIndex_ =
size_t(-1);
777 counterClockwise_ = (
unsigned int)(-1);
779 pixels_ = std::move(distinctPixels);
786 if (pixels_.size() > 1)
789 newPositions.reserve(pixels_.size() * 20);
791 for (
size_t n = 0; n < pixels_.size(); ++n)
796 int x = int(start.x());
797 int y = int(start.y());
798 const int xEnd = int(end.x());
799 const int yEnd = int(end.y());
803 while (x != xEnd || y != yEnd)
810 pixels_ = std::move(newPositions);
813 mostLeftIndex_ =
size_t(-1);
814 counterClockwise_ = (
unsigned int)(-1);
821 if (pixels_.size() <= 1)
827 newPixelPositions.reserve(pixels_.size());
829 VectorI2 currentDirection =
VectorI2(
int(pixels_.front().x() - pixels_.back().x()),
int(pixels_.front().y() - pixels_.back().y()));
831 for (
size_t n = 1; n < pixels_.size(); ++n)
833 const VectorI2 newDirection =
VectorI2(
int(pixels_[n].x() - pixels_[n - 1].x()),
int(pixels_[n].y() - pixels_[n - 1].y()));
835 if (!newDirection.
isNull())
837 if (!similar(currentDirection, newDirection))
839 currentDirection = newDirection;
840 newPixelPositions.push_back(pixels_[n - 1]);
845 const VectorI2 newDirection =
VectorI2(
int(pixels_.front().x() - pixels_.back().x()),
int(pixels_.front().y() - pixels_.back().y()));
847 if (currentDirection != newDirection)
849 newPixelPositions.push_back(pixels_.back());
854 ocean_assert(!newPixelPositions.empty());
857 ocean_assert(debugContour.
boundingBox() == boundingBox());
871 *
this = simplified();
877 ocean_assert(pixels_.size() >= 1);
884 ocean_assert(minimalSqrDistance >= 1u);
885 ocean_assert(startIndex < pixels_.size());
893 ocean_assert(!pixels_.empty());
895 unsigned int sqrDistance = pixels_.front().sqrDistance(pixels_.back());
897 for (
size_t n = 1; n < pixels_.size(); ++n)
899 const unsigned int localSqrDistance = pixels_[n - 1].sqrDistance(pixels_[n]);
913 ocean_assert(!pixels_.empty());
915 unsigned int sqrDistance = pixels_.front().sqrDistance(pixels_.back());
917 for (
size_t n = 1; n < pixels_.size(); ++n)
919 const unsigned int localSqrDistance = pixels_[n - 1].sqrDistance(pixels_[n]);
933 return !pixels_.empty();
939 ocean_assert(first.
x() != 0 || first.
y() != 0);
940 ocean_assert(second.
x() != 0 || second.
y() != 0);
945 const bool fastResult = first.
x() * second.
y() == second.
x() * first.
y()
946 && (0x80000000 & first.
x()) == (0x80000000 & second.
x())
947 && (0x80000000 & first.
y()) == (0x80000000 & second.
y());
955 ocean_assert(fastResult == (vf == vs));
960 return first.
x() * second.
y() == second.
x() * first.
y()
961 && (0x80000000 & first.
x()) == (0x80000000 & second.
x())
962 && (0x80000000 & first.
y()) == (0x80000000 & second.
y());
This class implements Bresenham's 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:63
unsigned int counterClockwise_
State whether this contour is counter clockwise: -1 undefined, 0 false, 1 true.
Definition PixelContour.h:336
void simplify()
Simplifies this (dense) contour to a sparse but identical contour.
Definition PixelContour.h:869
unsigned int smallestSqrDistanceBetweenPixels() const
Returns the smallest square distance between consecutive contour pixels.
Definition PixelContour.h:891
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:784
unsigned int largestSqrDistanceBetweenPixels() const
Returns the largest square distance between consecutive contour pixels.
Definition PixelContour.h:911
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:558
void makeDistinct()
Removes non distinct pixels from this contour.
Definition PixelContour.h:749
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
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:375
PixelPositionT< T > PixelPosition
Definition of a pixel position.
Definition PixelContour.h:76
PixelContourT()=default
Creates a new pixel contour object.
PixelContourT(PixelContourT< T > &&contour) noexcept
Move constructor.
Definition PixelContour.h:353
bool isDense() const
Returns whether this contour is dense.
Definition PixelContour.h:673
bool isDense4() const
Returns whether this contour is dense according to a 4-neighborhood.
Definition PixelContour.h:692
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:365
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:654
PixelContourT(const PixelContourT< T > &contour)
Copy constructor.
Definition PixelContour.h:343
PixelContourT< T > simplified() const
Returns the simplified contour of this contour which will be a sparse but identical contour.
Definition PixelContour.h:819
PixelBoundingBox boundingBox_
Bounding box of the contour.
Definition PixelContour.h:339
unsigned int area() const
Computes the area of a contour Uses the Shoelace formula to determine the area of a contour.
Definition PixelContour.h:522
PixelPositions pixels_
Pixel positions of the contour.
Definition PixelContour.h:330
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:385
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:424
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:405
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:937
bool isSimplified() const
Returns whether this contour is simplified.
Definition PixelContour.h:711
PixelBoundingBoxT< T > PixelBoundingBox
Definition of a pixel bounding box.
Definition PixelContour.h:86
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:600
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:395
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:875
size_t mostLeftIndex_
Index of the most left pixel.
Definition PixelContour.h:333
int areaSigned() const
Computes the signed area of a contour Uses the Shoelace formula to determine the area of a contour.
Definition PixelContour.h:528
This class provides basic numeric functionalities.
Definition Numeric.h:57
static constexpr T minValue()
Returns the min scalar value.
Definition Numeric.h:3259
static constexpr T maxValue()
Returns the max scalar value.
Definition Numeric.h:3253
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:703
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:715
bool isNull() const
Returns whether this vector is a null vector up to a small epsilon.
Definition Vector2.h:739
bool normalize()
Normalizes this vector.
Definition Vector2.h:605
unsigned int sqrDistance(const char first, const char second)
Returns the square distance between two values.
Definition base/Utilities.h:1159
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:994
PixelBoundingBoxT< unsigned int > PixelBoundingBox
Definition of the default PixelBoundingBox object with data type allowing only positive coordinate va...
Definition PixelBoundingBox.h:28
PixelPositionT< unsigned int > PixelPosition
Definition of the default PixelPosition object with a data type allowing only positive coordinate val...
Definition PixelPosition.h:32
std::vector< PixelContour > PixelContours
Definition of a vector holding pixel contours (with positive coordinate values).
Definition PixelContour.h:50
std::vector< PixelContourI > PixelContoursI
Definition of a vector holding pixel contours (with positive and negative coordinate values).
Definition PixelContour.h:57
float Scalar
Definition of a scalar type.
Definition Math.h:129
VectorT2< int > VectorI2
Definition of a 2D vector with integer values.
Definition Vector2.h:49
The namespace covering the entire Ocean framework.
Definition Accessor.h:15