From 6c3b195a57ae6605486d8d2b7cf767a536a960e4 Mon Sep 17 00:00:00 2001 From: Benjamin Knecht Date: Mon, 24 Feb 2025 17:33:09 +0100 Subject: [PATCH] Make sure serialization with single dict preserves old behavior --- .../objdetect/src/aruco/aruco_detector.cpp | 17 +++++--- .../objdetect/test/test_arucodetection.cpp | 42 +++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/modules/objdetect/src/aruco/aruco_detector.cpp b/modules/objdetect/src/aruco/aruco_detector.cpp index 3fabaf94c7..7f062b01cd 100644 --- a/modules/objdetect/src/aruco/aruco_detector.cpp +++ b/modules/objdetect/src/aruco/aruco_detector.cpp @@ -1407,13 +1407,18 @@ void ArucoDetector::refineDetectedMarkers(InputArray _image, const Board& _board } void ArucoDetector::write(FileStorage &fs) const { - fs << "dictionaries" << "["; - for (auto& dictionary : arucoDetectorImpl->dictionaries) { - fs << "{"; - dictionary.writeDictionary(fs); - fs << "}"; + // preserve old format for single dictionary case + if (1 == arucoDetectorImpl->dictionaries.size()) { + arucoDetectorImpl->dictionaries[0].writeDictionary(fs); + } else { + fs << "dictionaries" << "["; + for (auto& dictionary : arucoDetectorImpl->dictionaries) { + fs << "{"; + dictionary.writeDictionary(fs); + fs << "}"; + } + fs << "]"; } - fs << "]"; arucoDetectorImpl->detectorParams.writeDetectorParameters(fs); arucoDetectorImpl->refineParams.writeRefineParameters(fs); } diff --git a/modules/objdetect/test/test_arucodetection.cpp b/modules/objdetect/test/test_arucodetection.cpp index c3138312a4..00cce307a0 100644 --- a/modules/objdetect/test/test_arucodetection.cpp +++ b/modules/objdetect/test/test_arucodetection.cpp @@ -6,6 +6,15 @@ #include "opencv2/objdetect/aruco_detector.hpp" #include "opencv2/calib3d.hpp" +namespace cv::aruco { + bool operator==(const Dictionary& d1, const Dictionary& d2); + bool operator==(const Dictionary& d1, const Dictionary& d2) { + return d1.markerSize == d2.markerSize + && std::equal(d1.bytesList.begin(), d1.bytesList.end(), d2.bytesList.begin()) + && d1.maxCorrectionBits == d2.maxCorrectionBits; + }; +} + namespace opencv_test { namespace { /** @@ -675,6 +684,9 @@ TEST(CV_ArucoMultiDict, noDict) EXPECT_THROW({ detector.removeDictionary(0); }, Exception); + EXPECT_THROW({ + detector.setDictionaries({}); + }, Exception); } @@ -717,6 +729,36 @@ TEST(CV_ArucoMultiDict, multiMarkerDetection) } +TEST(CV_ArucoMultiDict, serialization) +{ + const std::string fileName("test_aruco_serialization.json"); + aruco::ArucoDetector detector; + { + FileStorage fs(fileName, FileStorage::Mode::WRITE); + detector.write(fs); + fs.release(); + FileStorage test_fs(fileName, FileStorage::Mode::READ); + aruco::ArucoDetector test_detector; + test_detector.read(test_fs.root()); + // compare default constructor result + EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_4X4_50), test_detector.getDictionary()); + } + detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_5X5_100)); + { + FileStorage fs(fileName, FileStorage::Mode::WRITE); + detector.write(fs); + fs.release(); + FileStorage test_fs(fileName, FileStorage::Mode::READ); + aruco::ArucoDetector test_detector; + test_detector.read(test_fs.root()); + // check for one additional dictionary + ASSERT_EQ(2ul, test_detector.getDictionaries().size()); + EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_4X4_50), test_detector.getDictionary()); + EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_5X5_100), test_detector.getDictionary(1)); + } +} + + struct ArucoThreading: public testing::TestWithParam { struct NumThreadsSetter {