From c16927605da799effea827345dbc116086e38891 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Wed, 24 Jul 2024 08:27:07 +0200 Subject: [PATCH] Merge pull request #25938 from vrabaud:charuco Properly check markers when none are provided. #25938 CharucoDetectorImpl::detectBoard finds temporary markers when none are provided but those are discarded when charucoDetectorImpl::checkBoard is called. ### 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 - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake --- .../objdetect/src/aruco/charuco_detector.cpp | 24 +++++++++++------ .../objdetect/test/test_charucodetection.cpp | 26 ++++++++++++------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/modules/objdetect/src/aruco/charuco_detector.cpp b/modules/objdetect/src/aruco/charuco_detector.cpp index 4f08747289..77f614d4d0 100644 --- a/modules/objdetect/src/aruco/charuco_detector.cpp +++ b/modules/objdetect/src/aruco/charuco_detector.cpp @@ -326,8 +326,21 @@ struct CharucoDetector::CharucoDetectorImpl { interpolateCornersCharucoLocalHom(_markerCorners, _markerIds, image, charucoCorners, charucoIds); // to return a charuco corner, its closest aruco markers should have been detected filterCornersWithoutMinMarkers(charucoCorners, charucoIds, _markerIds, charucoCorners, charucoIds); -} + } + void detectBoardWithCheck(InputArray image, OutputArray charucoCorners, OutputArray charucoIds, + InputOutputArrayOfArrays markerCorners, InputOutputArray markerIds) { + vector> tmpMarkerCorners; + vector tmpMarkerIds; + InputOutputArrayOfArrays _markerCorners = markerCorners.needed() ? markerCorners : tmpMarkerCorners; + InputOutputArray _markerIds = markerIds.needed() ? markerIds : tmpMarkerIds; + detectBoard(image, charucoCorners, charucoIds, _markerCorners, _markerIds); + if (checkBoard(_markerCorners, _markerIds, charucoCorners, charucoIds) == false) { + CV_LOG_DEBUG(NULL, "ChArUco board is built incorrectly"); + charucoCorners.release(); + charucoIds.release(); + } + } }; CharucoDetector::CharucoDetector(const CharucoBoard &board, const CharucoParameters &charucoParams, @@ -370,12 +383,7 @@ void CharucoDetector::setRefineParameters(const RefineParameters& refineParamete void CharucoDetector::detectBoard(InputArray image, OutputArray charucoCorners, OutputArray charucoIds, InputOutputArrayOfArrays markerCorners, InputOutputArray markerIds) const { - charucoDetectorImpl->detectBoard(image, charucoCorners, charucoIds, markerCorners, markerIds); - if (charucoDetectorImpl->checkBoard(markerCorners, markerIds, charucoCorners, charucoIds) == false) { - CV_LOG_DEBUG(NULL, "ChArUco board is built incorrectly"); - charucoCorners.release(); - charucoIds.release(); - } + charucoDetectorImpl->detectBoardWithCheck(image, charucoCorners, charucoIds, markerCorners, markerIds); } void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diamondCorners, OutputArray _diamondIds, @@ -480,7 +488,7 @@ void CharucoDetector::detectDiamonds(InputArray image, OutputArrayOfArrays _diam // interpolate the charuco corners of the diamond vector currentMarkerCorners; Mat aux; - charucoDetectorImpl->detectBoard(grey, currentMarkerCorners, aux, currentMarker, currentMarkerId); + charucoDetectorImpl->detectBoardWithCheck(grey, currentMarkerCorners, aux, currentMarker, currentMarkerId); // if everything is ok, save the diamond if(currentMarkerCorners.size() > 0ull) { diff --git a/modules/objdetect/test/test_charucodetection.cpp b/modules/objdetect/test/test_charucodetection.cpp index ab66e77665..4738c74acb 100644 --- a/modules/objdetect/test/test_charucodetection.cpp +++ b/modules/objdetect/test/test_charucodetection.cpp @@ -762,23 +762,29 @@ TEST_P(CharucoBoard, testWrongSizeDetection) ASSERT_FALSE(boardSize.width == boardSize.height); aruco::CharucoBoard board(boardSize, 1.f, 0.5f, aruco::getPredefinedDictionary(aruco::DICT_4X4_50)); - vector detectedCharucoIds, detectedArucoIds; - vector detectedCharucoCorners; - vector> detectedArucoCorners; Mat boardImage; board.generateImage(boardSize*40, boardImage); swap(boardSize.width, boardSize.height); aruco::CharucoDetector detector(aruco::CharucoBoard(boardSize, 1.f, 0.5f, aruco::getPredefinedDictionary(aruco::DICT_4X4_50))); // try detect board with wrong size - detector.detectBoard(boardImage, detectedCharucoCorners, detectedCharucoIds, detectedArucoCorners, detectedArucoIds); + for(int i: {0, 1}) { + vector detectedCharucoIds, detectedArucoIds; + vector detectedCharucoCorners; + vector> detectedArucoCorners; + if (i == 0) { + detector.detectBoard(boardImage, detectedCharucoCorners, detectedCharucoIds, detectedArucoCorners, detectedArucoIds); + // aruco markers must be found + ASSERT_EQ(detectedArucoIds.size(), board.getIds().size()); + ASSERT_EQ(detectedArucoCorners.size(), board.getIds().size()); + } else { + detector.detectBoard(boardImage, detectedCharucoCorners, detectedCharucoIds); + } - // aruco markers must be found - ASSERT_EQ(detectedArucoIds.size(), board.getIds().size()); - ASSERT_EQ(detectedArucoCorners.size(), board.getIds().size()); - // charuco corners should not be found in board with wrong size - ASSERT_TRUE(detectedCharucoCorners.empty()); - ASSERT_TRUE(detectedCharucoIds.empty()); + // charuco corners should not be found in board with wrong size + ASSERT_TRUE(detectedCharucoCorners.empty()); + ASSERT_TRUE(detectedCharucoIds.empty()); + } }