Files
opencv/modules/geometry/test/test_arclength.cpp
T
Alessio Roberto Antochi 16e83222dc Merge pull request #29547 from alessio-antochi:fix-approxpoly-test
Rework accuracy test for legacy C-API cvApproxPoly and CV_PerimeterTest - #29547

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake

**Details:**
This PR restores the deleted C-API `cvApproxPoly` tests (part of #24957).
I used `cv::pointPolygonTest` to make sure every original point is within the allowed `epsilon` distance to the final approximated polygon rather than calculate the distance to the corresponding line.

**Update:**
Restored `CV_PerimeterTest` *TEST(Imgproc_ContourPerimeter, accuracy)*.
Created a parameterized test for open/closed curves with int/float type shapes. I  also added a simple 10x10 square test.
2026-09-01 10:05:46 +03:00

98 lines
2.6 KiB
C++

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "test_precomp.hpp"
namespace opencv_test { namespace {
typedef testing::TestWithParam<bool> Geometry_ArcLength;
template<typename T>
static double refArcLength(const std::vector<T>& curve, bool is_closed)
{
double expected_length = 0.0;
size_t npoints = curve.size();
T prev_pt = curve[is_closed ? npoints - 1 : 0];
int start_idx = is_closed ? 0 : 1;
for (size_t i = start_idx; i < npoints; i++)
{
T pt = curve[i];
expected_length += cv::norm(pt - prev_pt);
prev_pt = pt;
}
return expected_length;
}
// Test arcLength accuracy
// Covers both open/closed curves and int/float coordinates
TEST_P(Geometry_ArcLength, accuracy_float)
{
const bool is_closed = GetParam();
RNG& rng = TS::ptr()->get_rng();
// generate random points
const int npoints = rng.uniform(3, 100);
vector<Point2f> curvef;
for (int i = 0; i < npoints; i++)
{
Point2f pt(rng.uniform(-1000.f, 1000.f), rng.uniform(-1000.f, 1000.f));
curvef.push_back(pt);
}
double length = cv::arcLength(curvef, is_closed);
double expected_length = refArcLength(curvef, is_closed);
EXPECT_NEAR(expected_length, length, FLT_EPSILON * 100 * expected_length);
}
TEST_P(Geometry_ArcLength, accuracy_int)
{
const bool is_closed = GetParam();
RNG& rng = TS::ptr()->get_rng();
// generate random points
const int npoints = rng.uniform(3, 100);
vector<Point2i> curvei;
for (int i = 0; i < npoints; i++)
{
Point2f pt(rng.uniform(-1000.f, 1000.f), rng.uniform(-1000.f, 1000.f));
curvei.push_back(Point2i((int)pt.x, (int)pt.y));
}
double length = cv::arcLength(curvei, is_closed);
double expected_length = refArcLength(curvei, is_closed);
EXPECT_NEAR(expected_length, length, FLT_EPSILON * expected_length);
}
// Simple test with a manually defined shape
TEST(Geometry_ArcLength, simple_square)
{
// create a 10x10 square
vector<Point2f> square;
square.push_back(Point2f(0, 0));
square.push_back(Point2f(10, 0));
square.push_back(Point2f(10, 10));
square.push_back(Point2f(0, 10));
// closed perimeter
EXPECT_DOUBLE_EQ(cv::arcLength(square, true), 40.0);
// open perimeter (missing the edge from (0,10) to (0,0))
EXPECT_DOUBLE_EQ(cv::arcLength(square, false), 30.0);
}
INSTANTIATE_TEST_CASE_P(
Geometry,
Geometry_ArcLength,
testing::Bool()
);
}} // namespace opencv_test