This commit is contained in:
SaraKuhnert 2025-06-04 19:50:01 -03:00 committed by GitHub
commit 21d262a183
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 1348 additions and 31 deletions

View File

@ -1560,3 +1560,12 @@
year = {2014},
url = {http://www.marcozuliani.com/docs/RANSAC4Dummies.pdf}
}
@article{Aggarwal1985,
author = {Aggarwal, A. and Chang, J. and Yap, Chee K.},
title = {Minimum area circumscribing Polygons},
year = {1985},
pages = {112--117},
journal = {The Visual Computer},
volume = {7},
url = {https://doi.org/10.1007/BF01898354}
}

View File

@ -3070,10 +3070,9 @@ Also, the special values #THRESH_OTSU or #THRESH_TRIANGLE may be combined with o
above values. In these cases, the function determines the optimal threshold value using the Otsu's
or Triangle algorithm and uses it instead of the specified thresh.
@note Currently, the Otsu's method is implemented only for CV_8UC1 and CV_16UC1 images,
and the Triangle's method is implemented only for CV_8UC1 images.
@note Currently, the Otsu's and Triangle methods are implemented only for 8-bit single-channel images.
@param src input array (multiple-channel, CV_8U, CV_16S, CV_16U, CV_32F or CV_64F).
@param src input array (multiple-channel, 8-bit or 32-bit floating point).
@param dst output array of the same size and type and the same number of channels as src.
@param thresh threshold value.
@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding
@ -3081,30 +3080,11 @@ types.
@param type thresholding type (see #ThresholdTypes).
@return the computed threshold value if Otsu's or Triangle methods used.
@sa thresholdWithMask, adaptiveThreshold, findContours, compare, min, max
@sa adaptiveThreshold, findContours, compare, min, max
*/
CV_EXPORTS_W double threshold( InputArray src, OutputArray dst,
double thresh, double maxval, int type );
/** @brief Same as #threshold, but with an optional mask
@note If the mask is empty, #thresholdWithMask is equivalent to #threshold.
If the mask is not empty, dst *must* be of the same size and type as src, so that
outliers pixels are left as-is
@param src input array (multiple-channel, 8-bit or 32-bit floating point).
@param dst output array of the same size and type and the same number of channels as src.
@param mask optional mask (same size as src, 8-bit).
@param thresh threshold value.
@param maxval maximum value to use with the #THRESH_BINARY and #THRESH_BINARY_INV thresholding
types.
@param type thresholding type (see #ThresholdTypes).
@return the computed threshold value if Otsu's or Triangle methods used.
@sa threshold, adaptiveThreshold, findContours, compare, min, max
*/
CV_EXPORTS_W double thresholdWithMask( InputArray src, InputOutputArray dst, InputArray mask,
double thresh, double maxval, int type );
/** @brief Applies an adaptive threshold to an array.
@ -4160,11 +4140,7 @@ CV_EXPORTS_W double contourArea( InputArray contour, bool oriented = false );
/** @brief Finds a rotated rectangle of the minimum area enclosing the input 2D point set.
The function calculates and returns the minimum-area bounding rectangle (possibly rotated) for a
specified point set. The angle of rotation represents the angle between the line connecting the starting
and ending points (based on the clockwise order with greatest index for the corner with greatest \f$y\f$)
and the horizontal axis. This angle always falls between \f$[-90, 0)\f$ because, if the object
rotates more than a rect angle, the next edge is used to measure the angle. The starting and ending points change
as the object rotates.Developer should keep in mind that the returned RotatedRect can contain negative
specified point set. Developer should keep in mind that the returned RotatedRect can contain negative
indices when data is close to the containing Mat element boundary.
@param points Input vector of 2D points, stored in std::vector\<\> or Mat
@ -4173,9 +4149,7 @@ CV_EXPORTS_W RotatedRect minAreaRect( InputArray points );
/** @brief Finds the four vertices of a rotated rect. Useful to draw the rotated rectangle.
The function finds the four vertices of a rotated rectangle. The four vertices are returned
in clockwise order starting from the point with greatest \f$y\f$. If two points have the
same \f$y\f$ coordinate the rightmost is the starting point. This function is useful to draw the
The function finds the four vertices of a rotated rectangle. This function is useful to draw the
rectangle. In C++, instead of using this function, you can directly use RotatedRect::points method. Please
visit the @ref tutorial_bounding_rotated_ellipses "tutorial on Creating Bounding rotated boxes and ellipses for contours" for more information.
@ -4219,6 +4193,30 @@ of the OutputArray must be CV_32F.
*/
CV_EXPORTS_W double minEnclosingTriangle( InputArray points, CV_OUT OutputArray triangle );
/**
@brief Finds a convex polygon of minimum area enclosing a 2D point set and returns its area.
This function takes a given set of 2D points and finds the enclosing polygon with k vertices and minimal
area. It takes the set of points and the parameter k as input and returns the area of the minimal
enclosing polygon.
The Implementation is based on a paper by Aggarwal, Chang and Yap @cite Aggarwal1985. They
provide a \f$\theta(n²log(n)log(k))\f$ algorighm for finding the minimal convex polygon with k
vertices enclosing a 2D convex polygon with n vertices (k < n). Since the #minEnclosingConvexPolygon
function takes a 2D point set as input, an additional preprocessing step of computing the convex hull
of the 2D point set is required. The complexity of the #convexHull function is \f$O(n log(n))\f$ which
is lower than \f$\theta(n²log(n)log(k))\f$. Thus the overall complexity of the function is
\f$O(n²log(n)log(k))\f$.
@param points Input vector of 2D points, stored in std::vector\<\> or Mat
@param polygon Output vector of 2D points defining the vertices of the enclosing polygon
@param k Number of vertices of the output polygon
*/
CV_EXPORTS_W double minEnclosingConvexPolygon ( InputArray points, OutputArray polygon, int k );
/** @brief Compares two shapes.
The function compares two shapes. All three implemented methods use the Hu invariants (see #HuMoments)

File diff suppressed because it is too large Load Diff

View File

@ -1069,5 +1069,130 @@ TEST(minEnclosingCircle, three_points)
EXPECT_LE(delta, 1.f);
}
//============================ minEnclosingPolygon tests ============================
TEST(minEnclosingPolygon, input_errors)
{
std::vector<cv::Point2f> kgon;
std::vector<cv::Point2f> ngon;
std::cout << "Four lines of \'invalid argument: ...\' are expected:" << std::endl;
ngon = {{0.0, 0.0}, {1.0, 1.0}};
EXPECT_NO_THROW(minEnclosingConvexPolygon(ngon, kgon, 3))
<< "unexpected exception: not enough points in input ngon (n < 3)";
ngon = {{0.0, 0.0}, {0.0, 0.0}, {1.0, 1.0}, {1.0, 1.0}};
EXPECT_NO_THROW(minEnclosingConvexPolygon(ngon, kgon, 3))
<< "unexpected exception: not enough different points in input ngon (double points)";
ngon = {{0.0, 0.0}, {1.0, 1.0}, {2.0, 2.0}, {3.0, 3.0}, {4.0, 4.0}};
EXPECT_NO_THROW(minEnclosingConvexPolygon(ngon, kgon, 3))
<< "unexpected exception: all points on line";
ngon = {{0.0, 0.0}, {0.0, 1.0}, {1.0, 0.0}, {1.0, 1.0}};
EXPECT_NO_THROW(minEnclosingConvexPolygon(ngon, kgon, 2)) << "unexpected exception: k < 3";
}
TEST(minEnclosingPolygon, input_warnings)
{
double area = -1.0;
std::vector<cv::Point2f> kgon;
std::vector<cv::Point2f> ngon;
std::cout << "Two lines of \'Warning: ...\' are expected:" << std::endl;
ngon = {{0.0, 0.0}, {0.0, 1.0}, {1.0, 0.0}, {1.0, 1.0}};
EXPECT_NO_THROW({
area = minEnclosingConvexPolygon(ngon, kgon, 4);
}) << "unexpected exception: n = k failed";
EXPECT_NEAR(area, 1.0, 1e-4) << "n = k: area not equal " << ngon;
ngon = {{0.0, 0.0}, {0.0, 1.0}, {1.0, 0.0}, {1.0, 1.0}};
EXPECT_NO_THROW({
area = minEnclosingConvexPolygon(ngon, kgon, 5);
}) << "unexpected exception: n < k failed";
EXPECT_NEAR(area, 1.0, 1e-4) << "n < k: area not equal " << ngon;
}
TEST(minEnclosingPolygon, unit_circle)
{
double area = -1.0;
std::vector<cv::Point2f> kgon;
std::vector<cv::Point2f> ngon;
const int n = 64;
const int k = 7;
for(int i = 0; i < n; i++)
{
cv::Point2f new_point(cos(i * 2.0 * M_PI / n), sin(i * 2.0 * M_PI / n));
ngon.push_back(new_point);
}
EXPECT_NO_THROW({
area = minEnclosingConvexPolygon(ngon, kgon, k);
});
EXPECT_GT(area, cv::contourArea(ngon));
EXPECT_EQ((int)kgon.size(), k);
}
TEST(minEnclosingPolygon, random_points)
{
double area = -1.0;
std::vector<cv::Point2f> kgon;
std::vector<cv::Point2f> ngon;
std::vector<cv::Point2f> ngonHull;
const int n = 100;
const int k = 7;
srand(0);
for(int i = 0; i < n; i++)
{
cv::Point2f new_point(rand() % 100 + 1, rand() % 100 + 1);
ngon.push_back(new_point);
}
cv::convexHull(ngon, ngonHull, true);
EXPECT_NO_THROW({
area = minEnclosingConvexPolygon(ngon, kgon, k);
});
EXPECT_GT(area, cv::contourArea(ngonHull));
EXPECT_EQ(kgon.size(), (size_t)k);
}
TEST(minEnclosingPolygon, pentagon)
{
double area;
std::vector<cv::Point2f> kgon;
std::vector<cv::Point2f> expectedKgon;
std::vector<cv::Point2f> ngon;
ngon = {{1, 0}, {0, 8}, {4, 12}, {8, 8}, {7, 0}};
EXPECT_NO_THROW({
area = minEnclosingConvexPolygon(ngon, kgon, 4);
});
expectedKgon = {{1, 0}, {-0.5, 12}, {8.5, 12}, {7, 0}};
EXPECT_EQ(area, cv::contourArea(expectedKgon));
ASSERT_EQ((int)kgon.size(), 4);
for (size_t i = 0; i < 4; i++)
{
bool match = false;
for (size_t j = 0; j < 4; j++)
{
if(expectedKgon[i].x == kgon[j].x && expectedKgon[i].y == kgon[j].y)
{
match = true;
break;
}
}
EXPECT_EQ(match, true);
}
}
}} // namespace
/* End of file. */