From eaa88e7bc7200a2b9b89b16a52c86eb9df5ad898 Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 25 Mar 2024 14:07:03 +0300 Subject: [PATCH] fix detect rotated grid, added test --- modules/calib3d/src/circlesgrid.cpp | 48 ++++++++++++++++------ modules/calib3d/src/circlesgrid.hpp | 1 + modules/calib3d/test/test_chesscorners.cpp | 37 +++++++++++++++++ 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/modules/calib3d/src/circlesgrid.cpp b/modules/calib3d/src/circlesgrid.cpp index df9534f755..d32913f9ef 100644 --- a/modules/calib3d/src/circlesgrid.cpp +++ b/modules/calib3d/src/circlesgrid.cpp @@ -701,22 +701,26 @@ bool CirclesGridFinder::isDetectionCorrect() { case CirclesGridFinderParameters::SYMMETRIC_GRID: { - if (holes.size() != patternSize.height) + rotatedGrid = holes.size() != patternSize.height && holes.size() == patternSize.width; + if (holes.size() != patternSize.height && holes.size() != patternSize.width) return false; - std::set vertices; + size_t num_vertices = 0ull; for (size_t i = 0; i < holes.size(); i++) { - if (holes[i].size() != patternSize.width) + if (holes[i].size() != patternSize.width && rotatedGrid == false) + { return false; - - for (size_t j = 0; j < holes[i].size(); j++) + } + else if (holes[i].size() != patternSize.height && rotatedGrid == true) { - vertices.insert(holes[i][j]); + rotatedGrid = false; + return false; } - } - return vertices.size() == patternSize.area(); + num_vertices += holes[i].size(); + } + return num_vertices == patternSize.area(); } case CirclesGridFinderParameters::ASYMMETRIC_GRID: @@ -1431,12 +1435,32 @@ Size CirclesGridFinder::getDetectedGridSize() const void CirclesGridFinder::getHoles(std::vector &outHoles) const { outHoles.clear(); - - for (size_t i = 0; i < holes.size(); i++) + if (rotatedGrid == false) { - for (size_t j = 0; j < holes[i].size(); j++) + for (size_t i = 0ull; i < holes.size(); i++) { - outHoles.push_back(keypoints[holes[i][j]]); + for (size_t j = 0ull; j < holes[i].size(); j++) + { + outHoles.push_back(keypoints[holes[i][j]]); + } + } + } + else + { + bool visit_all = false; + size_t j = 0ull; + while (visit_all != true) + { + visit_all = true; + for (size_t i = 0ull; i < holes.size(); i++) + { + if (j < holes[i].size()) + { + outHoles.push_back(keypoints[holes[i][j]]); + visit_all = false; + } + } + j++; } } } diff --git a/modules/calib3d/src/circlesgrid.hpp b/modules/calib3d/src/circlesgrid.hpp index f058af7a43..8fba89fd11 100644 --- a/modules/calib3d/src/circlesgrid.hpp +++ b/modules/calib3d/src/circlesgrid.hpp @@ -186,6 +186,7 @@ private: const cv::Size_ patternSize; cv::CirclesGridFinderParameters parameters; + bool rotatedGrid = false; CirclesGridFinder& operator=(const CirclesGridFinder&); CirclesGridFinder(const CirclesGridFinder&); diff --git a/modules/calib3d/test/test_chesscorners.cpp b/modules/calib3d/test/test_chesscorners.cpp index 56cb81e4ab..a63d5b3e83 100644 --- a/modules/calib3d/test/test_chesscorners.cpp +++ b/modules/calib3d/test/test_chesscorners.cpp @@ -792,5 +792,42 @@ TEST(Calib3d_AsymmetricCirclesPatternDetector, regression_19498) EXPECT_FALSE(res); } +TEST(Calib3d_RotatedCirclesPatternDetector, issue_24964) +{ + string path = cvtest::findDataFile("cv/cameracalibration/circles/circles_24964.png"); + Mat image = cv::imread(path); + ASSERT_FALSE(image.empty()) << "Can't read image: " << path; + + vector centers; + Size parrernSize(7, 6); + Mat goldCenters(parrernSize.height, parrernSize.width, CV_32FC2); + Point2f firstGoldCenter(380.f, 430.f); + for (int i = 0; i < parrernSize.height; i++) + { + for (int j = 0; j < parrernSize.width; j++) + { + goldCenters.at(i, j) = Point2f(firstGoldCenter.x + j * 100.f, firstGoldCenter.y + i * 100.f); + } + } + + bool found = false; + found = findCirclesGrid(image, parrernSize, centers, CALIB_CB_SYMMETRIC_GRID); + + EXPECT_TRUE(found); + ASSERT_EQ(centers.size(), (size_t)parrernSize.area()); + double error = calcError(centers, goldCenters); + EXPECT_LE(error, precise_success_error_level); + + // "rotate" the circle grid by 90 degrees + swap(parrernSize.height, parrernSize.width); + + found = findCirclesGrid(image, parrernSize, centers, CALIB_CB_SYMMETRIC_GRID); + error = calcError(centers, goldCenters.t()); + + EXPECT_TRUE(found); + ASSERT_EQ(centers.size(), (size_t)parrernSize.area()); + EXPECT_LE(error, precise_success_error_level); +} + }} // namespace /* End of file. */