1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-21 19:33:03 +04:00

fix bug in approxPolyDP: calculate distance to a segment, not to a line

This commit is contained in:
Galina Bykova
2025-12-01 21:22:11 +03:30
parent 1c712fe2ff
commit fc7e70ef4a
2 changed files with 32 additions and 5 deletions
+19 -5
View File
@@ -586,26 +586,40 @@ approxPolyDP_( const Point_<T>* src_contour, int count0, Point_<T>* dst_contour,
if( pos != slice.end )
{
double dx, dy, dist, max_dist = 0;
double dx, dy, max_dist_2_mul_segment_len_2 = 0;
dx = end_pt.x - start_pt.x;
dy = end_pt.y - start_pt.y;
double segment_len_2 = dx * dx + dy * dy;
CV_Assert( dx != 0 || dy != 0 );
while( pos != slice.end )
{
READ_PT(pt, pos);
dist = fabs((pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);
double projection = ((pt.x - start_pt.x) * dx + (pt.y - start_pt.y) * dy);
if( dist > max_dist )
double dist_2_mul_segment_len_2;
if ( projection < 0 )
{
max_dist = dist;
dist_2_mul_segment_len_2 = ((pt.x - start_pt.x) * (pt.x - start_pt.x) + (pt.y - start_pt.y) * (pt.y - start_pt.y)) * segment_len_2;
} else if ( projection > segment_len_2 )
{
dist_2_mul_segment_len_2 = ((pt.x - end_pt.x) * (pt.x - end_pt.x) + (pt.y - end_pt.y) * (pt.y - end_pt.y)) * segment_len_2;
} else
{
double dist = ((pt.y - start_pt.y) * dx - (pt.x - start_pt.x) * dy);
dist_2_mul_segment_len_2 = dist * dist;
}
if( dist_2_mul_segment_len_2 > max_dist_2_mul_segment_len_2 )
{
max_dist_2_mul_segment_len_2 = dist_2_mul_segment_len_2;
right_slice.start = (pos+count-1)%count;
}
}
le_eps = max_dist * max_dist <= eps * (dx * dx + dy * dy);
le_eps = max_dist_2_mul_segment_len_2 <= eps * segment_len_2;
}
else
{
+13
View File
@@ -377,6 +377,19 @@ TEST(Imgproc_ApproxPoly, bad_epsilon)
ASSERT_ANY_THROW(approxPolyDP(inputPoints, outputPoints, eps, false));
}
TEST(Imgproc_ApproxPoly, distace_between_point_and_segment)
{
vector<Point2f> inputPoints = {
{ {0.f, 0.f}, {4.f, 2.f}, {11.f, 1.f}, {8.f, 0.f} }
};
std::vector<Point2f> result;
approxPolyDP(inputPoints, result, 1.9, false);
vector<Point2f> expectedResult = {
{ {0.f, 0.f}, {11.f, 1.f}, {8.f, 0.f} }
};
ASSERT_EQ(result, expectedResult);
}
struct ApproxPolyN: public testing::Test
{
void SetUp()