From c26776b5155313ec65bf6be4fe691875fa43eb81 Mon Sep 17 00:00:00 2001 From: jonas Date: Fri, 14 Mar 2025 13:42:33 +0100 Subject: [PATCH] Remove getMarkerUncertainty from dict public API --- .../opencv2/objdetect/aruco_dictionary.hpp | 6 -- .../objdetect/src/aruco/aruco_detector.cpp | 66 ++++++++++++++++++- .../objdetect/src/aruco/aruco_dictionary.cpp | 59 ----------------- 3 files changed, 65 insertions(+), 66 deletions(-) diff --git a/modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp b/modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp index 760853546e..3c274ac33b 100644 --- a/modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp +++ b/modules/objdetect/include/opencv2/objdetect/aruco_dictionary.hpp @@ -71,12 +71,6 @@ class CV_EXPORTS_W_SIMPLE Dictionary { */ CV_WRAP int getDistanceToId(InputArray bits, int id, bool allRotations = true) const; - /** @brief Given a matrix containing the percentage of white pixels in each marker cell, returns the normalized marker uncertainty [0;1] for the specific id. - * The uncertainty is defined as percentage of incorrect pixel detections, with 0 describing a pixel perfect detection. - * The rotation is set to 0,1,2,3 for [0, 90, 180, 270] deg CCW rotations. - */ - CV_WRAP float getMarkerUnc(InputArray whitePixelRatio, int id, int rotation = 0, int borderBits = 1) const; - /** @brief Generate a canonical marker image */ CV_WRAP void generateImageMarker(int id, int sidePixels, OutputArray _img, int borderBits = 1) const; diff --git a/modules/objdetect/src/aruco/aruco_detector.cpp b/modules/objdetect/src/aruco/aruco_detector.cpp index 5ab726a703..2851e59caf 100644 --- a/modules/objdetect/src/aruco/aruco_detector.cpp +++ b/modules/objdetect/src/aruco/aruco_detector.cpp @@ -439,6 +439,70 @@ static int _getBorderErrors(const Mat &bits, int markerSize, int borderSize) { } +/** @brief Given a matrix containing the percentage of white pixels in each marker cell, returns the normalized marker uncertainty [0;1] for the specific id. + * The uncertainty is defined as percentage of incorrect pixel detections, with 0 describing a pixel perfect detection. + * The rotation is set to 0,1,2,3 for [0, 90, 180, 270] deg CCW rotations. + */ +static float _getMarkerUnc(const Dictionary& dictionary, const Mat &whitePixRatio, const int id, + const int rotation, const int borderSize) { + + CV_Assert(id >= 0 && id < dictionary.bytesList.rows); + const int markerSize = dictionary.markerSize; + const int sizeWithBorders = markerSize + 2 * borderSize; + + CV_Assert(markerSize > 0 && whitePixRatio.cols == sizeWithBorders && whitePixRatio.rows == sizeWithBorders); + + // Get border uncertainty. Assuming black borders, the uncertainty is the ratio of white pixels. + float tempBorderUnc = 0.f; + for(int y = 0; y < sizeWithBorders; y++) { + for(int k = 0; k < borderSize; k++) { + // Left and right vertical sides + tempBorderUnc += whitePixRatio.ptr(y)[k]; + tempBorderUnc += whitePixRatio.ptr(y)[sizeWithBorders - 1 - k]; + } + } + for(int x = borderSize; x < sizeWithBorders - borderSize; x++) { + for(int k = 0; k < borderSize; k++) { + // Top and bottom horizontal sides + tempBorderUnc += whitePixRatio.ptr(k)[x]; + tempBorderUnc += whitePixRatio.ptr(sizeWithBorders - 1 - k)[x]; + } + } + + // Get the ground truth bits and rotate them: + Mat groundTruthbits = dictionary.getBitsFromByteList(dictionary.bytesList.rowRange(id, id + 1), markerSize); + CV_Assert(groundTruthbits.cols == markerSize && groundTruthbits.rows == markerSize); + + if(rotation == 1){ + // 90 deg CCW + transpose(groundTruthbits, groundTruthbits); + flip(groundTruthbits, groundTruthbits,0); + + } else if (rotation == 2){ + // 180 deg CCW + flip(groundTruthbits, groundTruthbits,-1); + + } else if (rotation == 3){ + // 90 deg CW + transpose(groundTruthbits, groundTruthbits); + flip(groundTruthbits, groundTruthbits,1); + } + + // Get the inner marker uncertainty. For a white or black cell, the uncertainty is the ratio of black or white pixels respectively. + float tempInnerUnc = 0.f; + for(int y = borderSize; y < markerSize + borderSize; y++) { + for(int x = borderSize; x < markerSize + borderSize; x++) { + tempInnerUnc += abs(groundTruthbits.ptr(y - borderSize)[x - borderSize] - whitePixRatio.ptr(y)[x]); + } + } + + // Compute the overall normalized marker uncertainty + float normalizedMarkerUnc = (tempInnerUnc + tempBorderUnc) / (sizeWithBorders * sizeWithBorders); + + return normalizedMarkerUnc; +} + + /** * @brief Tries to identify one candidate given the dictionary * @return candidate typ. zero if the candidate is not valid, @@ -505,7 +569,7 @@ static uint8_t _identifyOneCandidate(const Dictionary& dictionary, const Mat& _i return 0; // compute the candidate's uncertainty - markerUnc = dictionary.getMarkerUnc(whitePixRatio, idx, rotation, params.markerBorderBits); + markerUnc = _getMarkerUnc(dictionary, whitePixRatio, idx, rotation, params.markerBorderBits); return typ; } diff --git a/modules/objdetect/src/aruco/aruco_dictionary.cpp b/modules/objdetect/src/aruco/aruco_dictionary.cpp index 15af31ea37..3d5f9b1bfd 100644 --- a/modules/objdetect/src/aruco/aruco_dictionary.cpp +++ b/modules/objdetect/src/aruco/aruco_dictionary.cpp @@ -110,65 +110,6 @@ bool Dictionary::identify(const Mat &onlyBits, int &idx, int &rotation, double m return idx != -1; } -float Dictionary::getMarkerUnc(InputArray _whitePixRatio, int id, int rotation, int borderSize) const { - - CV_Assert(id >= 0 && id < bytesList.rows); - const int sizeWithBorders = markerSize + 2 * borderSize; - - Mat whitePixRatio = _whitePixRatio.getMat(); - - CV_Assert(markerSize > 0 && whitePixRatio.cols == sizeWithBorders && whitePixRatio.rows == sizeWithBorders); - - // Get border uncertainty. Assuming black borders, the uncertainty is the ratio of white pixels. - float tempBorderUnc = 0.f; - for(int y = 0; y < sizeWithBorders; y++) { - for(int k = 0; k < borderSize; k++) { - // Left and right vertical sides - tempBorderUnc += whitePixRatio.ptr(y)[k]; - tempBorderUnc += whitePixRatio.ptr(y)[sizeWithBorders - 1 - k]; - } - } - for(int x = borderSize; x < sizeWithBorders - borderSize; x++) { - for(int k = 0; k < borderSize; k++) { - // Top and bottom horizontal sides - tempBorderUnc += whitePixRatio.ptr(k)[x]; - tempBorderUnc += whitePixRatio.ptr(sizeWithBorders - 1 - k)[x]; - } - } - - // Get the ground truth bits and rotate them: - Mat groundTruthbits = getBitsFromByteList(bytesList.rowRange(id, id + 1), markerSize); - CV_Assert(groundTruthbits.cols == markerSize && groundTruthbits.rows == markerSize); - - if(rotation == 1){ - // 90 deg CCW - transpose(groundTruthbits, groundTruthbits); - flip(groundTruthbits, groundTruthbits,0); - - } else if (rotation == 2){ - // 180 deg CCW - flip(groundTruthbits, groundTruthbits,-1); - - } else if (rotation == 3){ - // 90 deg CW - transpose(groundTruthbits, groundTruthbits); - flip(groundTruthbits, groundTruthbits,1); - } - - // Get the inner marker uncertainty. For a white or black cell, the uncertainty is the ratio of black or white pixels respectively. - float tempInnerUnc = 0.f; - for(int y = borderSize; y < markerSize + borderSize; y++) { - for(int x = borderSize; x < markerSize + borderSize; x++) { - tempInnerUnc += abs(groundTruthbits.ptr(y - borderSize)[x - borderSize] - whitePixRatio.ptr(y)[x]); - } - } - - // Compute the overall normalized marker uncertainty - float normalizedMarkerUnc = (tempInnerUnc + tempBorderUnc) / (sizeWithBorders * sizeWithBorders); - - return normalizedMarkerUnc; -} - int Dictionary::getDistanceToId(InputArray bits, int id, bool allRotations) const {