From 6f9f8f49dd0cbd19838f964f189a9abc7a93d79c Mon Sep 17 00:00:00 2001 From: Marius Wachtler Date: Tue, 23 Sep 2025 19:00:24 -0500 Subject: [PATCH] Speedup ChArUco by avoiding temporary copies This speeds up processing a 132x128 board by more than 100 times. This methods return std::vectors<> which means lots of copies and allocations. --- .../objdetect/src/aruco/charuco_detector.cpp | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/modules/objdetect/src/aruco/charuco_detector.cpp b/modules/objdetect/src/aruco/charuco_detector.cpp index 48446c86e3..37aca01b36 100644 --- a/modules/objdetect/src/aruco/charuco_detector.cpp +++ b/modules/objdetect/src/aruco/charuco_detector.cpp @@ -32,8 +32,10 @@ struct CharucoDetector::CharucoDetectorImpl { const Mat chIds = charucoIds.getMat(); const vector& boardIds = board.getIds(); - const vector > nearestMarkerIdx = board.getNearestMarkerIdx(); - vector distance(board.getNearestMarkerIdx().size(), Point2f(0.f, std::numeric_limits::max())); + const vector > nearestMarkerIdx = board.getNearestMarkerIdx(); // only copy the vectors once + const vector > nearestMarkerCorners = board.getNearestMarkerCorners(); + + vector distance(nearestMarkerIdx.size(), Point2f(0.f, std::numeric_limits::max())); // distance[i].x: max distance from the i-th charuco corner to charuco corner-forming markers. // The two charuco corner-forming markers of i-th charuco corner are defined in getNearestMarkerIdx()[i] // distance[i].y: min distance from the charuco corner to other markers. @@ -52,7 +54,7 @@ struct CharucoDetector::CharucoDetectorImpl { const int nearestMarkerId1 = boardIds[nearestMarkerIdx[chId][0]]; const int nearestMarkerId2 = boardIds[nearestMarkerIdx[chId][1]]; if (nearestMarkerId1 == idMaker || nearestMarkerId2 == idMaker) { - int nearestCornerId = nearestMarkerId1 == idMaker ? board.getNearestMarkerCorners()[chId][0] : board.getNearestMarkerCorners()[chId][1]; + int nearestCornerId = nearestMarkerId1 == idMaker ? nearestMarkerCorners[chId][0] : nearestMarkerCorners[chId][1]; Point2f nearestCorner = mCorners[j].ptr(0)[nearestCornerId]; // distToNearest: distance from the charuco corner to charuco corner-forming markers float distToNearest = sqrt(normL2Sqr(nearestCorner - charucoCorner)); @@ -84,18 +86,21 @@ struct CharucoDetector::CharucoDetectorImpl { InputArray charucoCorners) { size_t nCharucoCorners = charucoCorners.getMat().total(); - CV_Assert(board.getNearestMarkerIdx().size() == nCharucoCorners); + const vector > nearestMarkerIdx = board.getNearestMarkerIdx(); // only copy the vectors once + const vector > nearestMarkerCorners = board.getNearestMarkerCorners(); + + CV_Assert(nearestMarkerIdx.size() == nCharucoCorners); vector winSizes(nCharucoCorners, Size(-1, -1)); for(size_t i = 0ull; i < nCharucoCorners; i++) { if(charucoCorners.getMat().at((int)i) == Point2f(-1.f, -1.f)) continue; - if(board.getNearestMarkerIdx()[i].empty()) continue; + if(nearestMarkerIdx[i].empty()) continue; double minDist = -1; int counter = 0; // calculate the distance to each of the closest corner of each closest marker - for(size_t j = 0; j < board.getNearestMarkerIdx()[i].size(); j++) { + for(size_t j = 0; j < nearestMarkerIdx[i].size(); j++) { // find marker - int markerId = board.getIds()[board.getNearestMarkerIdx()[i][j]]; + int markerId = board.getIds()[nearestMarkerIdx[i][j]]; int markerIdx = -1; for(size_t k = 0; k < markerIds.getMat().total(); k++) { if(markerIds.getMat().at((int)k) == markerId) { @@ -105,7 +110,7 @@ struct CharucoDetector::CharucoDetectorImpl { } if(markerIdx == -1) continue; Point2f markerCorner = - markerCorners.getMat(markerIdx).at(board.getNearestMarkerCorners()[i][j]); + markerCorners.getMat(markerIdx).at(nearestMarkerCorners[i][j]); Point2f charucoCorner = charucoCorners.getMat().at((int)i); double dist = norm(markerCorner - charucoCorner); if(minDist == -1) minDist = dist; // if first distance, just assign it @@ -212,6 +217,8 @@ struct CharucoDetector::CharucoDetectorImpl { vector transformations(nMarkers); vector validTransform(nMarkers, false); const auto& ids = board.getIds(); + const vector > nearestMarkerIdx = board.getNearestMarkerIdx(); // only copy the vectors once + for(size_t i = 0ull; i < nMarkers; i++) { vector markerObjPoints2D; int markerId = markerIds.getMat().at((int)i); @@ -227,15 +234,16 @@ struct CharucoDetector::CharucoDetectorImpl { double det = determinant(transformations[i]); validTransform[i] = std::abs(det) > 1e-6; } - size_t nCharucoCorners = (size_t)board.getChessboardCorners().size(); + const vector chessboardCorners = board.getChessboardCorners(); + size_t nCharucoCorners = (size_t)chessboardCorners.size(); vector allChessboardImgPoints(nCharucoCorners, Point2f(-1, -1)); // for each charuco corner, calculate its interpolation position based on the closest markers // homographies for(size_t i = 0ull; i < nCharucoCorners; i++) { - Point2f objPoint2D = Point2f(board.getChessboardCorners()[i].x, board.getChessboardCorners()[i].y); + Point2f objPoint2D = Point2f(chessboardCorners[i].x, chessboardCorners[i].y); vector interpolatedPositions; - for(size_t j = 0ull; j < board.getNearestMarkerIdx()[i].size(); j++) { - int markerId = board.getIds()[board.getNearestMarkerIdx()[i][j]]; + for(size_t j = 0ull; j < nearestMarkerIdx[i].size(); j++) { + int markerId = board.getIds()[nearestMarkerIdx[i][j]]; int markerIdx = -1; for(size_t k = 0ull; k < markerIds.getMat().total(); k++) { if(markerIds.getMat().at((int)k) == markerId) { @@ -274,13 +282,14 @@ struct CharucoDetector::CharucoDetectorImpl { CV_Assert(charucoParameters.minMarkers >= 0 && charucoParameters.minMarkers <= 2); vector filteredCharucoCorners; vector filteredCharucoIds; + const vector > nearestMarkerIdx = board.getNearestMarkerIdx(); // only copy the vectors once // for each charuco corner for(unsigned int i = 0; i < allCharucoIds.getMat().total(); i++) { int currentCharucoId = allCharucoIds.getMat().at(i); int totalMarkers = 0; // nomber of closest marker detected // look for closest markers - for(unsigned int m = 0; m < board.getNearestMarkerIdx()[currentCharucoId].size(); m++) { - int markerId = board.getIds()[board.getNearestMarkerIdx()[currentCharucoId][m]]; + for(unsigned int m = 0; m < nearestMarkerIdx[currentCharucoId].size(); m++) { + int markerId = board.getIds()[nearestMarkerIdx[currentCharucoId][m]]; bool found = false; for(unsigned int k = 0; k < allArucoIds.getMat().total(); k++) { if(allArucoIds.getMat().at(k) == markerId) {