From ca527040e2bee65bce6df50773252779d3335dfb Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 4 Sep 2023 18:28:28 +0300 Subject: [PATCH] fix refineDetectedMarkers, add test --- .../misc/python/test/test_objdetect_aruco.py | 33 +++++++++++++++++++ .../objdetect/src/aruco/aruco_detector.cpp | 8 ++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/modules/objdetect/misc/python/test/test_objdetect_aruco.py b/modules/objdetect/misc/python/test/test_objdetect_aruco.py index d63a19cd2f..dda58b6460 100644 --- a/modules/objdetect/misc/python/test/test_objdetect_aruco.py +++ b/modules/objdetect/misc/python/test/test_objdetect_aruco.py @@ -186,6 +186,39 @@ class aruco_objdetect_test(NewOpenCVTests): self.assertEqual((1, 4, 2), refine_corners[0].shape) np.testing.assert_array_equal(corners, refine_corners) + def test_charuco_refine(self): + aruco_dict = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_50) + board_size = (3, 4) + board = cv.aruco.CharucoBoard(board_size, 1., .7, aruco_dict) + aruco_detector = cv.aruco.ArucoDetector(aruco_dict) + charuco_detector = cv.aruco.CharucoDetector(board) + cell_size = 100 + image = board.generateImage((cell_size*board_size[0], cell_size*board_size[1])) + camera = np.array([[1, 0, 0.5], + [0, 1, 0.5], + [0, 0, 1]]) + dist = np.array([0, 0, 0, 0, 0], dtype=np.float32).reshape(1, -1) + + # generate gold corners of the ArUco markers for the test + gold_corners = np.array(board.getObjPoints())[:, :, 0:2]*cell_size + + # detect corners + markerCorners, markerIds, _ = aruco_detector.detectMarkers(image) + + # test refine + rejected = [markerCorners[-1]] + markerCorners, markerIds = markerCorners[:-1], markerIds[:-1] + markerCorners, markerIds, _, _ = aruco_detector.refineDetectedMarkers(image, board, markerCorners, markerIds, + rejected, cameraMatrix=camera, distCoeffs=dist) + + charucoCorners, charucoIds, _, _ = charuco_detector.detectBoard(image, markerCorners=markerCorners, + markerIds=markerIds) + self.assertEqual(len(charucoIds), 6) + self.assertEqual(len(markerIds), 6) + + for i, id in enumerate(markerIds.reshape(-1)): + np.testing.assert_allclose(gold_corners[id], markerCorners[i].reshape(4, 2), 0.01, 1.) + def test_write_read_dictionary(self): try: aruco_dict = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_5X5_50) diff --git a/modules/objdetect/src/aruco/aruco_detector.cpp b/modules/objdetect/src/aruco/aruco_detector.cpp index 395bb49338..84ccc6e323 100644 --- a/modules/objdetect/src/aruco/aruco_detector.cpp +++ b/modules/objdetect/src/aruco/aruco_detector.cpp @@ -1000,7 +1000,13 @@ static inline void _projectUndetectedMarkers(const Board &board, InputOutputArra OutputArray undetectedMarkersIds) { Mat rvec, tvec; // first estimate board pose with the current avaible markers Mat objPoints, imgPoints; // object and image points for the solvePnP function - board.matchImagePoints(detectedCorners, detectedIds, objPoints, imgPoints); + // To refine corners of ArUco markers the function refineDetectedMarkers() find an aruco markers pose from 3D-2D point correspondences. + // To find 3D-2D point correspondences uses matchImagePoints(). + // The method matchImagePoints() works with ArUco corners (in Board/GridBoard cases) or with ChArUco corners (in CharucoBoard case). + // To refine corners of ArUco markers we need work with ArUco corners only in all boards. + // To call matchImagePoints() with ArUco corners for all boards we need to call matchImagePoints() from base class Board. + // The method matchImagePoints() implemented in Pimpl and we need to create temp Board object to call the base method. + Board(board.getObjPoints(), board.getDictionary(), board.getIds()).matchImagePoints(detectedCorners, detectedIds, objPoints, imgPoints); if (objPoints.total() < 4ull) // at least one marker from board so rvec and tvec are valid return; solvePnP(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec);