Remove add/removeDictionary and retain ABI of set/getDictionary

functions
This commit is contained in:
Benjamin Knecht 2025-02-24 18:01:10 +01:00
parent 6c3b195a57
commit 314f99f7a0
4 changed files with 37 additions and 88 deletions

View File

@ -373,67 +373,34 @@ public:
CV_WRAP void detectMarkersMultiDict(InputArray image, OutputArrayOfArrays corners, OutputArray ids,
OutputArrayOfArrays rejectedImgPoints = noArray(), OutputArray dictIndices = noArray()) const;
/** @brief Returns a specific dictionary from the set of dictionaries used for marker detection.
/** @brief Returns first dictionary from internal list used for marker detection.
*
* @param index Index of the dictionary to retrieve. Default is 0, returning the first dictionary if multiple are set.
*
* Returns the dictionary at the specified index from the internal collection of dictionaries used by the ArucoDetector.
* If only one dictionary is set, or if the index is 0, this method will return that dictionary.
* If multiple dictionaries are in use (e.g., for dictionary cascade), this allows access to each dictionary individually.
* @note If the index is out of bounds, the function throws an error.
* @return The first dictionary from the configured ArucoDetector.
*/
CV_WRAP const Dictionary& getDictionary(int index = 0) const;
CV_WRAP const Dictionary& getDictionary() const;
/** @brief Sets a specific dictionary in the list of dictionaries used for marker detection, replacing the dictionary at the given index.
/** @brief Sets and replaces the first dictionary in internal list to be used for marker detection.
*
* @param dictionary The dictionary to set at the specified index.
* @param index Index of the dictionary to set. Default is 0, replacing the first dictionary if multiple are set.
*
* Sets the dictionary at the specified index within the internal collection of dictionaries used by the ArucoDetector.
* If implementing a dictionary cascade or similar, this method allows for replacing specific dictionaries within the collection.
* @note If the index is out of bounds, the method is going to throw an error.
* @param dictionary The new dictionary that will replace the first dictionary in the internal list.
*/
CV_WRAP void setDictionary(const Dictionary& dictionary, int index = 0);
CV_WRAP void setDictionary(const Dictionary& dictionary);
/** @brief Returns all dictionaries currently used for marker detection as a vector.
*
* @return A constant reference to a std::vector<Dictionary> containing all dictionaries used by the ArucoDetector.
*
* Provides access to the entire set of Dictionary objects currently configured within the ArucoDetector.
* This is useful for inspecting the dictionaries being used, iterating through them, or determining the number of dictionaries in use.
* @return A std::vector<Dictionary> containing all dictionaries used by the ArucoDetector.
*/
CV_WRAP const std::vector<Dictionary>& getDictionaries() const;
CV_WRAP std::vector<Dictionary> getDictionaries() const;
/** @brief Sets the entire collection of dictionaries to be used for marker detection, replacing any existing dictionaries.
*
* @param dictionaries A std::vector<Dictionary> containing the new set of dictionaries to be used.
*
* Configures the ArucoDetector to use the provided vector of Dictionary objects for marker detection.
* Configures the ArucoDetector to use the provided vector of dictionaries for marker detection.
* This method replaces any dictionaries that were previously set.
* @note Setting an empty vector of dictionaries will throw an error.
*/
CV_WRAP void setDictionaries(const std::vector<Dictionary>& dictionaries);
/** @brief Adds a new dictionary to the collection of dictionaries used for marker detection.
*
* @param dictionary The dictionary to add to the collection.
*
* Appends the provided Dictionary object to the internal collection of dictionaries used by the ArucoDetector.
* This method is useful when you want to extend the set of dictionaries already in use without replacing them entirely.
*/
CV_WRAP void addDictionary(const Dictionary& dictionary);
/** @brief Removes a dictionary from the collection of dictionaries at the specified index.
*
* @param index Index of the dictionary to remove from the collection.
*
* Removes the Dictionary object at the specified index from the internal collection of dictionaries.
* After removing a dictionary, the indices of subsequent dictionaries in the collection will be shifted.
* @note If the index is out of bounds, the function will throw. It will also not allow removing the last
* dictionary of the internal collection.
*/
CV_WRAP void removeDictionary(int index);
CV_WRAP const DetectorParameters& getDetectorParameters() const;
CV_WRAP void setDetectorParameters(const DetectorParameters& detectorParameters);

View File

@ -1439,22 +1439,19 @@ void ArucoDetector::read(const FileNode &fn) {
arucoDetectorImpl->refineParams.readRefineParameters(fn);
}
const Dictionary& ArucoDetector::getDictionary(int index) const {
CV_Assert(index >= 0 && static_cast<size_t>(index) < arucoDetectorImpl->dictionaries.size());
return arucoDetectorImpl->dictionaries[index];
const Dictionary& ArucoDetector::getDictionary() const {
return arucoDetectorImpl->dictionaries[0];
}
void ArucoDetector::setDictionary(const Dictionary& dictionary, int index) {
// special case: if index is 0, we add the dictionary to the list to preserve the old behavior
CV_Assert(index == 0 || (index >= 0 && static_cast<size_t>(index) < arucoDetectorImpl->dictionaries.size()));
if (index == 0 && arucoDetectorImpl->dictionaries.empty()) {
void ArucoDetector::setDictionary(const Dictionary& dictionary) {
if (arucoDetectorImpl->dictionaries.empty()) {
arucoDetectorImpl->dictionaries.push_back(dictionary);
} else {
arucoDetectorImpl->dictionaries.at(index) = dictionary;
arucoDetectorImpl->dictionaries[0] = dictionary;
}
}
const vector<Dictionary>& ArucoDetector::getDictionaries() const {
vector<Dictionary> ArucoDetector::getDictionaries() const {
return arucoDetectorImpl->dictionaries;
}
@ -1463,17 +1460,6 @@ void ArucoDetector::setDictionaries(const vector<Dictionary>& dictionaries) {
arucoDetectorImpl->dictionaries = dictionaries;
}
void ArucoDetector::addDictionary(const Dictionary& dictionary) {
arucoDetectorImpl->dictionaries.push_back(dictionary);
}
void ArucoDetector::removeDictionary(int index) {
CV_Assert(index >= 0 && static_cast<size_t>(index) < arucoDetectorImpl->dictionaries.size());
// disallow no dictionaries
CV_Assert(arucoDetectorImpl->dictionaries.size() > 1ul);
arucoDetectorImpl->dictionaries.erase(arucoDetectorImpl->dictionaries.begin() + index);
}
const DetectorParameters& ArucoDetector::getDetectorParameters() const {
return arucoDetectorImpl->detectorParams;
}

View File

@ -647,33 +647,31 @@ TEST(CV_ArucoDetectMarkers, regression_contour_24220)
}
}
TEST(CV_ArucoMultiDict, addRemoveDictionary)
TEST(CV_ArucoMultiDict, setGetDictionaries)
{
// using default constructor that pre-configures DICT_4X4_50
aruco::ArucoDetector detector;
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_5X5_100));
const auto& dicts = detector.getDictionaries();
vector<aruco::Dictionary> dictionaries = {aruco::getPredefinedDictionary(aruco::DICT_4X4_50), aruco::getPredefinedDictionary(aruco::DICT_5X5_100)};
aruco::ArucoDetector detector(dictionaries);
vector<aruco::Dictionary> dicts = detector.getDictionaries();
ASSERT_EQ(dicts.size(), 2ul);
EXPECT_EQ(dicts[0].markerSize, 4);
EXPECT_EQ(dicts[1].markerSize, 5);
detector.removeDictionary(0);
ASSERT_EQ(dicts.size(), 1ul);
EXPECT_EQ(dicts[0].markerSize, 5);
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_6X6_100));
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_7X7_250));
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_APRILTAG_25h9));
detector.removeDictionary(0);
dictionaries.clear();
dictionaries.push_back(aruco::getPredefinedDictionary(aruco::DICT_6X6_100));
dictionaries.push_back(aruco::getPredefinedDictionary(aruco::DICT_7X7_250));
dictionaries.push_back(aruco::getPredefinedDictionary(aruco::DICT_APRILTAG_25h9));
detector.setDictionaries(dictionaries);
dicts = detector.getDictionaries();
ASSERT_EQ(dicts.size(), 3ul);
EXPECT_EQ(dicts[0].markerSize, 6);
EXPECT_EQ(dicts[1].markerSize, 7);
EXPECT_EQ(dicts[2].markerSize, 5);
detector.setDictionary(aruco::getPredefinedDictionary(aruco::DICT_APRILTAG_36h10), 1);
auto dict = detector.getDictionary();
EXPECT_EQ(dict.markerSize, 6);
detector.setDictionary(aruco::getPredefinedDictionary(aruco::DICT_APRILTAG_16h5));
dicts = detector.getDictionaries();
ASSERT_EQ(dicts.size(), 3ul);
EXPECT_EQ(dicts[0].markerSize, 4);
EXPECT_EQ(dicts[1].markerSize, 6);
EXPECT_EQ(dicts[1].markerSize, 7);
EXPECT_EQ(dicts[2].markerSize, 5);
}
@ -681,9 +679,6 @@ TEST(CV_ArucoMultiDict, addRemoveDictionary)
TEST(CV_ArucoMultiDict, noDict)
{
aruco::ArucoDetector detector;
EXPECT_THROW({
detector.removeDictionary(0);
}, Exception);
EXPECT_THROW({
detector.setDictionaries({});
}, Exception);
@ -743,7 +738,7 @@ TEST(CV_ArucoMultiDict, serialization)
// compare default constructor result
EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_4X4_50), test_detector.getDictionary());
}
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_5X5_100));
detector.setDictionaries({aruco::getPredefinedDictionary(aruco::DICT_4X4_50), aruco::getPredefinedDictionary(aruco::DICT_5X5_100)});
{
FileStorage fs(fileName, FileStorage::Mode::WRITE);
detector.write(fs);
@ -752,9 +747,10 @@ TEST(CV_ArucoMultiDict, serialization)
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));
auto dicts = test_detector.getDictionaries();
ASSERT_EQ(2ul, dicts.size());
EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_4X4_50), dicts[0]);
EXPECT_EQ(aruco::getPredefinedDictionary(aruco::DICT_5X5_100), dicts[1]);
}
}

View File

@ -134,17 +134,17 @@ class CV_ArucoRefine : public cvtest::BaseTest {
public:
CV_ArucoRefine(ArucoAlgParams arucoAlgParams)
{
aruco::Dictionary dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
vector<aruco::Dictionary> dictionaries = {aruco::getPredefinedDictionary(aruco::DICT_6X6_250),
aruco::getPredefinedDictionary(aruco::DICT_5X5_250),
aruco::getPredefinedDictionary(aruco::DICT_4X4_250),
aruco::getPredefinedDictionary(aruco::DICT_7X7_250)};
aruco::DetectorParameters params;
params.minDistanceToBorder = 3;
params.cornerRefinementMethod = (int)aruco::CORNER_REFINE_SUBPIX;
if (arucoAlgParams == ArucoAlgParams::USE_ARUCO3)
params.useAruco3Detection = true;
aruco::RefineParameters refineParams(10.f, 3.f, true);
detector = aruco::ArucoDetector(dictionary, params, refineParams);
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_5X5_250));
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_4X4_250));
detector.addDictionary(aruco::getPredefinedDictionary(aruco::DICT_7X7_250));
detector = aruco::ArucoDetector(dictionaries, params, refineParams);
}
protected: