From fc7e70ef4a5cec91a4029cc749d5ee390f5e5f22 Mon Sep 17 00:00:00 2001 From: Galina Bykova Date: Mon, 1 Dec 2025 21:22:11 +0330 Subject: [PATCH] fix bug in approxPolyDP: calculate distance to a segment, not to a line --- modules/imgproc/src/approx.cpp | 24 +++++++++++++++++++----- modules/imgproc/test/test_approxpoly.cpp | 13 +++++++++++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/modules/imgproc/src/approx.cpp b/modules/imgproc/src/approx.cpp index 6c89f1d879..433ca669d5 100644 --- a/modules/imgproc/src/approx.cpp +++ b/modules/imgproc/src/approx.cpp @@ -586,26 +586,40 @@ approxPolyDP_( const Point_* src_contour, int count0, Point_* 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 { diff --git a/modules/imgproc/test/test_approxpoly.cpp b/modules/imgproc/test/test_approxpoly.cpp index 2b07c1a7b5..347b03ae8a 100644 --- a/modules/imgproc/test/test_approxpoly.cpp +++ b/modules/imgproc/test/test_approxpoly.cpp @@ -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 inputPoints = { + { {0.f, 0.f}, {4.f, 2.f}, {11.f, 1.f}, {8.f, 0.f} } + }; + std::vector result; + approxPolyDP(inputPoints, result, 1.9, false); + vector expectedResult = { + { {0.f, 0.f}, {11.f, 1.f}, {8.f, 0.f} } + }; + ASSERT_EQ(result, expectedResult); +} + struct ApproxPolyN: public testing::Test { void SetUp()