From f3292a63d960d2ba4599c51ad36f63ca4076e9bf Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Thu, 29 Aug 2024 22:04:04 +0200 Subject: [PATCH 01/17] Upgrade opencv version, more stable Dockerfile, upgrade python utils --- Dockerfile | 33 +++++++++++++++++++----------- README.md | 2 +- python_utils/requirements_dev.txt | 6 +++--- python_utils/requirements_prod.txt | 6 +++--- 4 files changed, 28 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index a9db8e55..10119bc0 100755 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,9 @@ -FROM ubuntu:20.04 as prod +FROM ubuntu:24.04 as prod ENV DEBIAN_FRONTEND noninteractive RUN apt update && apt install -y --no-install-recommends apt-utils && \ apt upgrade -y && apt autoremove -y && \ - apt install -y build-essential cmake && \ + apt install -y build-essential cmake wget unzip git && \ apt install -y python-is-python3 python3-pip && \ rm -rf /var/lib/apt/lists/* @@ -15,7 +15,13 @@ WORKDIR /home #------------------------------ # # INSTALL OPENCV 4 # #------------------------------ # -RUN apt update && apt install -y libopencv-dev && \ +RUN wget -O opencv.zip https://github.com/opencv/opencv/archive/4.10.0.zip && \ + wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/4.10.0.zip && \ + unzip opencv.zip && unzip opencv_contrib.zip && \ + mkdir -p build && cd build && \ + cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.10.0/modules ../opencv-4.10.0 && \ + cmake --build . --target install && \ + cd .. && rm opencv.zip && rm opencv_contrib.zip && rm -rf opencv-4.10.0 && rm -rf opencv_contrib-4.10.0 && rm -rf build && \ rm -rf /var/lib/apt/lists/* #------------------------------ # @@ -27,25 +33,28 @@ RUN apt update && apt install -y libboost-all-dev && \ #------------------------------ # # Install Ceres # #------------------------------ # -RUN apt update && \ - apt install -y libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev && \ +RUN apt update && apt install -y libgoogle-glog-dev libgflags-dev libatlas-base-dev libeigen3-dev libsuitesparse-dev && \ rm -rf /var/lib/apt/lists/* -RUN apt update && apt install -y git && \ - /bin/bash -c "git clone https://ceres-solver.googlesource.com/ceres-solver && \ +RUN git clone --branch 20240722.0 --single-branch https://github.com/abseil/abseil-cpp.git && \ + cd abseil-cpp && mkdir build && cd build && \ + cmake .. && cmake --build . --target install && \ + cd .. && rm -rf abseil-cpp && \ + rm -rf /var/lib/apt/lists/* +RUN git clone --branch 2.2.0 --single-branch https://github.com/ceres-solver/ceres-solver.git && \ cd ceres-solver && mkdir build && cd build && cmake .. && \ make && make install && \ - cd /home && rm -rf ceres-solver" && \ + cd /home && rm -rf ceres-solver && \ rm -rf /var/lib/apt/lists/* # Install python requirements for python_utils scripts RUN --mount=type=bind,source=python_utils/requirements_prod.txt,target=/tmp/requirements.txt \ - pip install --requirement /tmp/requirements.txt && \ + python -m pip install --requirement /tmp/requirements.txt --break-system-packages && \ rm -rf /var/lib/apt/lists/* FROM prod as dev -RUN apt update && apt install -y python3-opencv && \ - rm -rf /var/lib/apt/lists/* +# RUN apt update && apt install -y python3-opencv && \ +# rm -rf /var/lib/apt/lists/* #------------------------------ # # Doxygen # @@ -67,5 +76,5 @@ RUN apt update && apt install -y cppcheck clang-tidy valgrind lcov && \ # Install python requirements for python_utils scripts RUN --mount=type=bind,source=python_utils/requirements_dev.txt,target=/tmp/requirements.txt \ - pip install --requirement /tmp/requirements.txt && \ + python -m pip install --requirement /tmp/requirements.txt --break-system-packages && \ rm -rf /var/lib/apt/lists/* \ No newline at end of file diff --git a/README.md b/README.md index 916a31e6..3646a68a 100755 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Toolbox described in the paper ["MC-Calib: A generic and robust calibration tool # Installation -Requirements: Ceres, Boost, OpenCV {4.2.x, 4.5.x}, c++17 +Requirements: c++17, Ceres==2.2.0, Boost==1.83, OpenCV==4.10.0 For Windows users, follow [this installation guide](/docs/Windows.md) diff --git a/python_utils/requirements_dev.txt b/python_utils/requirements_dev.txt index 2f2858b1..b5cb3329 100644 --- a/python_utils/requirements_dev.txt +++ b/python_utils/requirements_dev.txt @@ -1,4 +1,4 @@ isort==5.13.2 -black==24.4.2 -mypy==1.10.0 -pylint==3.2.2 \ No newline at end of file +black==24.8.0 +mypy==1.11.2 +pylint==3.2.6 \ No newline at end of file diff --git a/python_utils/requirements_prod.txt b/python_utils/requirements_prod.txt index 158559c4..fba3388c 100755 --- a/python_utils/requirements_prod.txt +++ b/python_utils/requirements_prod.txt @@ -1,3 +1,3 @@ -numpy==1.24.4 -matplotlib==3.7.5 -opencv-python==4.9.0.80 +numpy==2.1.0 +matplotlib==3.9.2 +opencv-python==4.10.0.84 From 574c051e19593bdab699012f5dcc4de2c996e73f Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Thu, 29 Aug 2024 22:16:23 +0200 Subject: [PATCH 02/17] Update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3646a68a..edbe3643 100755 --- a/README.md +++ b/README.md @@ -36,11 +36,11 @@ There are several ways to get the environment ready. Choose any of them: 2. It is also possible to build the docker environment manually (see [instructions](/docs/Docker.md)) -3. Alternatively, every dependency can be installed independently without docker: +3. Alternatively, every dependency can be installed manually without docker: - - [Install](https://docs.opencv.org/4.5.2/d7/d9f/tutorial_linux_install.html) OpenCV 4.5.x. Either instal system-wide with `sudo make install` or link to your `build` in `CmakeLists.txt`. + - [Install](https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html) OpenCV - - Follow [installation guidelines](http://ceres-solver.org/installation.html#linux) to install Ceres. + - Follow [installation guidelines](http://ceres-solver.org/installation.html#linux) to install Ceres - Install boost: From 0f7db5ca3b8568678d22eb75633b757b9db87653 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Fri, 30 Aug 2024 21:15:31 +0200 Subject: [PATCH 03/17] Delete downloaded files as they are installed to system path --- Dockerfile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/Dockerfile b/Dockerfile index 10119bc0..f0800cec 100755 --- a/Dockerfile +++ b/Dockerfile @@ -21,7 +21,8 @@ RUN wget -O opencv.zip https://github.com/opencv/opencv/archive/4.10.0.zip && \ mkdir -p build && cd build && \ cmake -DOPENCV_EXTRA_MODULES_PATH=../opencv_contrib-4.10.0/modules ../opencv-4.10.0 && \ cmake --build . --target install && \ - cd .. && rm opencv.zip && rm opencv_contrib.zip && rm -rf opencv-4.10.0 && rm -rf opencv_contrib-4.10.0 && rm -rf build && \ + cd /home && rm opencv.zip && rm opencv_contrib.zip && \ + rm -rf opencv-4.10.0 && rm -rf opencv_contrib-4.10.0 && rm -rf build && \ rm -rf /var/lib/apt/lists/* #------------------------------ # @@ -38,7 +39,7 @@ RUN apt update && apt install -y libgoogle-glog-dev libgflags-dev libatlas-base- RUN git clone --branch 20240722.0 --single-branch https://github.com/abseil/abseil-cpp.git && \ cd abseil-cpp && mkdir build && cd build && \ cmake .. && cmake --build . --target install && \ - cd .. && rm -rf abseil-cpp && \ + cd /home && rm -rf abseil-cpp && \ rm -rf /var/lib/apt/lists/* RUN git clone --branch 2.2.0 --single-branch https://github.com/ceres-solver/ceres-solver.git && \ cd ceres-solver && mkdir build && cd build && cmake .. && \ @@ -53,19 +54,16 @@ RUN --mount=type=bind,source=python_utils/requirements_prod.txt,target=/tmp/requ FROM prod as dev -# RUN apt update && apt install -y python3-opencv && \ -# rm -rf /var/lib/apt/lists/* - #------------------------------ # # Doxygen # #------------------------------ # RUN apt update && apt install -y flex bison && \ - /bin/bash -c "git clone https://github.com/doxygen/doxygen.git && \ + git clone https://github.com/doxygen/doxygen.git && \ cd doxygen && mkdir build && cd build &&\ cmake -G 'Unix Makefiles' .. && \ make && \ make install && \ - cd /home && rm -rf doxygen" && \ + cd /home && rm -rf doxygen && \ rm -rf /var/lib/apt/lists/* #------------------------------ # From acc8e0c62e5d028badaf3f2eafa4c26e613b54ce Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Fri, 30 Aug 2024 21:16:16 +0200 Subject: [PATCH 04/17] Upgrade to OpenCV 4.10.0 --- .../src/create_charuco_boards.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/apps/create_charuco_boards/src/create_charuco_boards.cpp b/apps/create_charuco_boards/src/create_charuco_boards.cpp index 85c5905d..7870490b 100644 --- a/apps/create_charuco_boards/src/create_charuco_boards.cpp +++ b/apps/create_charuco_boards/src/create_charuco_boards.cpp @@ -59,27 +59,28 @@ int main(int argc, char *argv[]) { } // Create the charuco - cv::Ptr dict = - cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000); - std::vector> charucoBoards; + const cv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); + std::vector charucoBoards; int offset_count = 0; for (std::size_t i = 0; i < num_board; i++) { // declare the board - cv::Ptr charuco = cv::aruco::CharucoBoard::create( - number_x_square_per_board[i], number_y_square_per_board[i], + const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), length_square, length_marker, dict); + // If it is the first board then just use the standard idx if (i != 0) { - int id_offset = charucoBoards[i - 1]->ids.size() + offset_count; + int id_offset = charucoBoards[i - 1].getIds().size() + offset_count; offset_count = id_offset; - for (auto &id : charuco->ids) { - id += id_offset; - } + // for (auto &id : charuco->getIds()) { + // id += id_offset; + // } } + // create the charuco board charucoBoards.push_back(charuco); cv::Mat boardImage; - charucoBoards[i]->draw( + charucoBoards[i].generateImage( cv::Size(resolution_x_per_board[i], resolution_y_per_board[i]), boardImage, 10, 1); // Display marker From 1e56e7b6952010b7c095dd8742df80b753a12fab Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Sat, 31 Aug 2024 09:12:20 +0200 Subject: [PATCH 05/17] random_shuffle -> shuffle --- McCalib/src/Camera.cpp | 13 +++++++++---- McCalib/src/geometrytools.cpp | 11 ++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/McCalib/src/Camera.cpp b/McCalib/src/Camera.cpp index 824821a9..8aa49c5c 100644 --- a/McCalib/src/Camera.cpp +++ b/McCalib/src/Camera.cpp @@ -1,8 +1,11 @@ -#include "opencv2/core/core.hpp" #include -#include -#include #include +#include +#include + +#include +#include "opencv2/core/core.hpp" +#include #include "Camera.hpp" #include "OptimizationCeres.h" @@ -167,7 +170,9 @@ void Camera::initializeCalibration() { std::srand(unsigned(std::time(0))); std::vector shuffled_board_ind(indbv.size()); std::iota(shuffled_board_ind.begin(), shuffled_board_ind.end(), 0); - random_shuffle(shuffled_board_ind.begin(), shuffled_board_ind.end()); + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(shuffled_board_ind.begin(), shuffled_board_ind.end(), g); // nb of boards used for the initial estimation of intrinsic parameters //(at least 50 boards for perspective) diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index 3176e044..23f5d00e 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "geometrytools.hpp" #include "logger.h" @@ -165,7 +167,9 @@ void ransacTriangulation(std::vector point2d, // Ransac iterations while (N > trialcount && countit < it) { // pick 2 points - std::random_shuffle(myvector.begin(), myvector.end()); + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(myvector.begin(), myvector.end(), g); std::array idx = {myvector[0], myvector[1], myvector[2], myvector[3]}; @@ -245,9 +249,10 @@ cv::Mat ransacP3P(const std::vector &scenePoints, // Ransac iterations while (N > trialcount && countit < it) { - // pick 4 points - std::random_shuffle(myvector.begin(), myvector.end()); + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(myvector.begin(), myvector.end(), g); std::array idx = {myvector[0], myvector[1], myvector[2], myvector[3]}; From 56cb55b2990ce2687e7c45f41d6cc19bb5294143 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Sat, 31 Aug 2024 10:29:42 +0200 Subject: [PATCH 06/17] WIP --- CMakeLists.txt | 1 - McCalib/include/Board.hpp | 2 +- McCalib/include/McCalib.hpp | 5 ++-- McCalib/src/Board.cpp | 1 + McCalib/src/McCalib.cpp | 24 ++++++++++--------- .../src/create_charuco_boards.cpp | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4137fe09..8c1919c0 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,6 +92,5 @@ endif (DOXYGEN_FOUND) ########################################################################## add_subdirectory(apps/create_charuco_boards) add_subdirectory(McCalib) -find_library(McCalib REQUIRED) add_subdirectory(apps/calibrate) add_subdirectory(tests) diff --git a/McCalib/include/Board.hpp b/McCalib/include/Board.hpp index e69e5a1f..a5bc796f 100644 --- a/McCalib/include/Board.hpp +++ b/McCalib/include/Board.hpp @@ -40,7 +40,7 @@ class Board final { std::map> frames_; // Charuco board - cv::Ptr charuco_board_; // vector of charuco boards + cv::aruco::CharucoBoard charuco_board_; // Functions Board() = delete; diff --git a/McCalib/include/McCalib.hpp b/McCalib/include/McCalib.hpp index ea27ebf6..904d285e 100644 --- a/McCalib/include/McCalib.hpp +++ b/McCalib/include/McCalib.hpp @@ -35,11 +35,10 @@ class Calibration final { public: // Parameters unsigned int nb_camera_, nb_board_; - cv::Ptr dict_ = cv::aruco::getPredefinedDictionary( + const cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the // charuco board - cv::Ptr charuco_params_ = - cv::aruco::DetectorParameters::create(); // parameters for detection + cv::aruco::DetectorParameters charuco_params_ = cv::aruco::DetectorParameters(); // parameters for detection float min_perc_pts_; // images path diff --git a/McCalib/src/Board.cpp b/McCalib/src/Board.cpp index 7e939b8d..667dbb73 100644 --- a/McCalib/src/Board.cpp +++ b/McCalib/src/Board.cpp @@ -10,6 +10,7 @@ #include "Frame.hpp" #include "logger.h" + /** * @brief Initialize Board object * diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 8d0f3ad1..9d04d55b 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -114,18 +114,18 @@ Calibration::Calibration(const std::string config_path) { boards_index.resize(nb_board_); std::iota(boards_index.begin(), boards_index.end(), 0); } - std::map> charuco_boards; + std::map charuco_boards; int offset_count = 0; for (int i = 0; i <= max_board_idx; i++) { - cv::Ptr charuco = cv::aruco::CharucoBoard::create( - number_x_square_per_board_[i], number_y_square_per_board_[i], + const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), length_square, length_marker, dict_); if (i != 0) // If it is the first board then just use the standard idx { - int id_offset = charuco_boards[i - 1]->ids.size() + offset_count; + int id_offset = charuco_boards[i - 1].getIds().size() + offset_count; offset_count = id_offset; - for (auto &id : charuco->ids) - id += id_offset; + // for (int &id : charuco.getIds()) + // id += id_offset; } charuco_boards[i] = charuco; } @@ -301,15 +301,17 @@ void Calibration::detectBoardsInImageWithCamera(const std::string frame_path, // key == board id, value == ID corners on checkerboard std::map> charuco_idx; - charuco_params_->adaptiveThreshConstant = 1; + charuco_params_.adaptiveThreshConstant = 1; - for (std::size_t i = 0; i < nb_board_; i++) { - cv::aruco::detectMarkers(image, boards_3d_[i]->charuco_board_->dictionary, - marker_corners[i], marker_idx[i], charuco_params_); + for (std::size_t i = 0; i < nb_board_; i++) { + cv::aruco::ArucoDetector detector(boards_3d_[i]->charuco_board_.getDictionary(), charuco_params_); + detector.detectMarkers(image, marker_corners[i], marker_idx[i]); + + // cv::aruco::detectMarkers(image, dict, marker_corners[i], marker_idx[i], &charuco_params_); if (marker_corners[i].size() > 0) { cv::aruco::interpolateCornersCharuco(marker_corners[i], marker_idx[i], - image, boards_3d_[i]->charuco_board_, + image, &boards_3d_[i]->charuco_board_, charuco_corners[i], charuco_idx[i]); } diff --git a/apps/create_charuco_boards/src/create_charuco_boards.cpp b/apps/create_charuco_boards/src/create_charuco_boards.cpp index 7870490b..da4fd6ba 100644 --- a/apps/create_charuco_boards/src/create_charuco_boards.cpp +++ b/apps/create_charuco_boards/src/create_charuco_boards.cpp @@ -59,7 +59,7 @@ int main(int argc, char *argv[]) { } // Create the charuco - const cv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); + const cv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000); std::vector charucoBoards; int offset_count = 0; for (std::size_t i = 0; i < num_board; i++) { From ac17b28b1f80a8bf9c7d9921b0e5a35059e0a1b9 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Sat, 31 Aug 2024 11:04:28 +0200 Subject: [PATCH 07/17] Adding namespace to all McCalib related files --- McCalib/include/Board.hpp | 6 +- McCalib/include/BoardObs.hpp | 4 ++ McCalib/include/Camera.hpp | 4 ++ McCalib/include/CameraGroup.hpp | 4 ++ McCalib/include/CameraGroupObs.hpp | 4 ++ McCalib/include/CameraObs.hpp | 4 ++ McCalib/include/Frame.hpp | 4 ++ McCalib/include/Graph.hpp | 3 +- McCalib/include/McCalib.hpp | 2 +- McCalib/include/Object3D.hpp | 4 ++ McCalib/include/Object3DObs.hpp | 4 ++ McCalib/include/OptimizationCeres.h | 102 +--------------------------- McCalib/include/geometrytools.hpp | 6 +- McCalib/include/point_refinement.h | 4 +- McCalib/src/Board.cpp | 3 + McCalib/src/BoardObs.cpp | 4 ++ McCalib/src/Camera.cpp | 4 ++ McCalib/src/CameraGroup.cpp | 4 ++ McCalib/src/CameraGroupObs.cpp | 4 ++ McCalib/src/CameraObs.cpp | 4 ++ McCalib/src/Frame.cpp | 4 ++ McCalib/src/Graph.cpp | 2 +- McCalib/src/McCalib.cpp | 27 ++++---- McCalib/src/Object3D.cpp | 4 ++ McCalib/src/Object3DObs.cpp | 4 ++ McCalib/src/geometrytools.cpp | 6 +- tests/simple_unit_tests_example.cpp | 2 +- tests/test_calibration.cpp | 11 ++- tests/test_geometrytools.cpp | 10 +-- 29 files changed, 117 insertions(+), 131 deletions(-) diff --git a/McCalib/include/Board.hpp b/McCalib/include/Board.hpp index a5bc796f..9e8d8ed1 100644 --- a/McCalib/include/Board.hpp +++ b/McCalib/include/Board.hpp @@ -6,6 +6,8 @@ #include #include +namespace McCalib { + class BoardObs; class Frame; @@ -40,7 +42,7 @@ class Board final { std::map> frames_; // Charuco board - cv::aruco::CharucoBoard charuco_board_; + cv::Ptr charuco_board_; // Functions Board() = delete; @@ -49,3 +51,5 @@ class Board final { void insertNewBoard(std::shared_ptr new_board); void insertNewFrame(std::shared_ptr new_frame); }; + +} //namespace McCalib diff --git a/McCalib/include/BoardObs.hpp b/McCalib/include/BoardObs.hpp index 7a09395e..0ae171b8 100644 --- a/McCalib/include/BoardObs.hpp +++ b/McCalib/include/BoardObs.hpp @@ -7,6 +7,8 @@ #include #include +namespace McCalib { + class Camera; class Board; @@ -60,3 +62,5 @@ class BoardObs final { cv::Mat getRotVec() const; cv::Mat getTransVec() const; }; + +} //namespace McCalib \ No newline at end of file diff --git a/McCalib/include/Camera.hpp b/McCalib/include/Camera.hpp index 5ae777c9..a845bef0 100644 --- a/McCalib/include/Camera.hpp +++ b/McCalib/include/Camera.hpp @@ -11,6 +11,8 @@ #include "Frame.hpp" #include "Object3DObs.hpp" +namespace McCalib { + /** * @class Camera * @@ -64,3 +66,5 @@ class Camera final { void setIntrinsics(const cv::Mat K, const cv::Mat distortion_vector); bool checkBorderToleranceFisheye(std::shared_ptr board_obs); }; + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/include/CameraGroup.hpp b/McCalib/include/CameraGroup.hpp index e2069af3..aa2f5be7 100644 --- a/McCalib/include/CameraGroup.hpp +++ b/McCalib/include/CameraGroup.hpp @@ -12,6 +12,8 @@ #include "Frame.hpp" #include "Object3DObs.hpp" +namespace McCalib { + /** * @class CameraGroup * @@ -63,3 +65,5 @@ class CameraGroup final { void refineCameraGroupAndObjects(const int nb_iterations); void refineCameraGroupAndObjectsAndIntrinsics(const int nb_iterations); }; + +} // namespace McCalib diff --git a/McCalib/include/CameraGroupObs.hpp b/McCalib/include/CameraGroupObs.hpp index 6185fdbf..a722df36 100644 --- a/McCalib/include/CameraGroupObs.hpp +++ b/McCalib/include/CameraGroupObs.hpp @@ -8,6 +8,8 @@ #include #include +namespace McCalib { + class CameraGroup; /** @@ -50,3 +52,5 @@ class CameraGroupObs final { cv::Mat getObjectTransVec(int object_id); void updateObjObsPose(); }; + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/include/CameraObs.hpp b/McCalib/include/CameraObs.hpp index 5dd80b14..c620e130 100644 --- a/McCalib/include/CameraObs.hpp +++ b/McCalib/include/CameraObs.hpp @@ -8,6 +8,8 @@ #include #include +namespace McCalib { + class Camera; /** @@ -37,3 +39,5 @@ class CameraObs final { void insertNewBoard(std::shared_ptr new_board); void insertNewObject(std::shared_ptr new_object); }; + +} // namespace McCalib diff --git a/McCalib/include/Frame.hpp b/McCalib/include/Frame.hpp index 8ae282c9..c01b7399 100644 --- a/McCalib/include/Frame.hpp +++ b/McCalib/include/Frame.hpp @@ -11,6 +11,8 @@ #include "CameraObs.hpp" #include "Object3DObs.hpp" +namespace McCalib { + /** * @class Frame * @@ -57,3 +59,5 @@ class Frame final { insertNewCameraGroupObs(std::shared_ptr new_cam_group_obs, const int camera_group_idx); }; + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/include/Graph.hpp b/McCalib/include/Graph.hpp index 68339176..3b148ebb 100644 --- a/McCalib/include/Graph.hpp +++ b/McCalib/include/Graph.hpp @@ -5,6 +5,7 @@ #include #include + /** * @class Graph * @@ -45,4 +46,4 @@ class Graph final { std::vector getPath(const std::vector &p_map, const Vertex &source, const Vertex &destination); -}; +}; \ No newline at end of file diff --git a/McCalib/include/McCalib.hpp b/McCalib/include/McCalib.hpp index 904d285e..a5469e96 100644 --- a/McCalib/include/McCalib.hpp +++ b/McCalib/include/McCalib.hpp @@ -35,7 +35,7 @@ class Calibration final { public: // Parameters unsigned int nb_camera_, nb_board_; - const cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( +cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the // charuco board cv::aruco::DetectorParameters charuco_params_ = cv::aruco::DetectorParameters(); // parameters for detection diff --git a/McCalib/include/Object3D.hpp b/McCalib/include/Object3D.hpp index db5febef..608acd41 100644 --- a/McCalib/include/Object3D.hpp +++ b/McCalib/include/Object3D.hpp @@ -6,6 +6,8 @@ #include #include +namespace McCalib { + class Board; class BoardObs; class Object3DObs; @@ -68,3 +70,5 @@ class Object3D final { void refineObject(const int nb_iterations); void updateObjectPts(); }; + +} // namespace McCalib diff --git a/McCalib/include/Object3DObs.hpp b/McCalib/include/Object3DObs.hpp index 3c16af1c..4500acc7 100644 --- a/McCalib/include/Object3DObs.hpp +++ b/McCalib/include/Object3DObs.hpp @@ -8,6 +8,8 @@ #include #include +namespace McCalib { + class Camera; class Board; class BoardObs; @@ -82,3 +84,5 @@ class Object3DObs final { cv::Mat getRotInGroupVec() const; cv::Mat getTransInGroupVec() const; }; + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/include/OptimizationCeres.h b/McCalib/include/OptimizationCeres.h index b3985059..2ad5961b 100755 --- a/McCalib/include/OptimizationCeres.h +++ b/McCalib/include/OptimizationCeres.h @@ -662,104 +662,4 @@ struct ReprojectionError_CameraGroupAndObjectRefAndIntrinsics { bool refine_camera; bool refine_board; int distortion_type; -}; - -/* -template -Eigen::Matrix -AngleAxisToRotationMatrix(const Eigen::Matrix& rvec) { - T angle = rvec.norm(); - if (angle == T(0)) { - return Eigen::Matrix::Identity(); - } - - Eigen::Matrix axis; - axis = rvec.normalized(); - - Eigen::Matrix rmat; - rmat = Eigen::AngleAxis(angle, axis); - - return rmat; -} - - - -// Refine handeye calibration -struct TransformationError { - TransformationError(double r1_x, double r1_y, double r1_z, double t1_x, double -t1_y, double t1_z, double r2_x, double r2_y, double r2_z, double t2_x, double -t2_y, double t2_z) : r1_x(r1_x), r1_y(r1_y), r1_z(r1_z), t1_x(t1_x), t1_y(t1_y), -t1_z(t1_z), r2_x(r2_x), r2_y(r2_y), r2_z(r2_z), t2_x(t2_x), t2_y(t2_y), -t2_z(t2_z) {} - - template - bool operator()(const T *const transform, - T *residuals) const { - - // 1. convert to rotation matrix for relative 1 and 2 - Eigen::Matrix r1, r2; - r1(0,0) = r1_x; r1(1,0) = r1_y; r1(2,0) = r1_z; - r2(0,0) = r2_x; r2(1,0) = r2_y; r2(2,0) = r2_z; - Eigen::Matrix R1 = AngleAxisToRotationMatrix(r1); - Eigen::Matrix R2 = AngleAxisToRotationMatrix(r2); - Eigen::Matrix t1, t2; - t1(0,0) = t1_x; t1(1,0) = t1_y; t1(2,0) = t1_z; - t2(0,0) = t2_x; t2(1,0) = t2_y; t2(2,0) = t2_z; - - Eigen::Matrix4d Trans1; // Your Transformation Matrix - Trans1.setIdentity(); // Set to Identity to make bottom row of Matrix -0,0,0,1 Trans1.block<3,3>(0,0) = R1; Trans1.block<3,1>(0,3) = t1; - Eigen::Matrix4d Trans2; // Your Transformation Matrix - Trans2.setIdentity(); // Set to Identity to make bottom row of Matrix -0,0,0,1 Trans2.block<3,3>(0,0) = R2; Trans2.block<3,1>(0,3) = t2; - - //2. convert the transform - Eigen::Matrix rt; - Eigen::Matrix tt; - rt(0,0) = (transform[0]); rt(1,0) = (transform[1]); rt(2,0) = -(transform[2]); Eigen::Matrix Rt = AngleAxisToRotationMatrix(rt); - tt(0,0) = (transform[3]); tt(1,0) = (transform[4]); tt(2,0) = -(transform[5]); Eigen::Matrix Trans; // Your Transformation Matrix - Trans(0,0) = Rt(0,0); Trans(0,1) = Rt(0,1); Trans(0,2) = Rt(0,2); Trans(0,3) -= tt(0,0); Trans(1,0) = Rt(1,0); Trans(1,1) = Rt(1,1); Trans(1,2) = Rt(1,2); -Trans(1,3) = tt(1,0); Trans(2,0) = Rt(2,0); Trans(2,1) = Rt(2,1); Trans(2,2) = -Rt(2,2); Trans(2,3) = tt(2,0); - - Eigen::Matrix4d Error = (Trans - Trans2*Trans*Trans1.inverse()); - //r1.row(0) << r1_x, r1_y, r1_z; - //Map r1; //(r11); - - - //AngleAxisToRotationMatrix(axis_angle, matrix); - // 2. convert the "transform" ro rotation matrix - - // 2. Compute errors matrix - residuals[0] = T(Error(0,0)); - residuals[1] = T(Error(1,0)); - residuals[2] = T(Error(2,0)); - residuals[3] = T(Error(3,0)); - residuals[4] = T(Error(0,1)); - residuals[5] = T(Error(1,1)); - residuals[6] = T(Error(2,1)); - residuals[7] = T(Error(3,1)); - residuals[8] = T(Error(0,2)); - residuals[9] = T(Error(1,2)); - residuals[10] = T(Error(2,2)); - residuals[11] = T(Error(3,2)); - - return true; - } - - static ceres::CostFunction *Create(const double r1_x, const double r1_y, const -double r1_z, const double t1_x, const double t1_y, const double t1_z, const -double r2_x, const double r2_y, const double r2_z, const double t2_x, const -double t2_y, const double t2_z) { return (new -ceres::AutoDiffCostFunction( new -TransformationError(r1_x, r1_y, r1_z, t1_x, t1_y, t1_z, r2_x, r2_y, r2_z, t2_x, -t2_y, t2_z))); - } - double r1_x, r1_y, r1_z; - double t1_x, t1_y, t1_z; - double r2_x, r2_y, r2_z; - double t2_x, t2_y, t2_z; -};*/ \ No newline at end of file +}; \ No newline at end of file diff --git a/McCalib/include/geometrytools.hpp b/McCalib/include/geometrytools.hpp index e53c4e5c..a8b24005 100644 --- a/McCalib/include/geometrytools.hpp +++ b/McCalib/include/geometrytools.hpp @@ -6,6 +6,8 @@ #include #include +namespace McCalib { + cv::Mat RT2Proj(cv::Mat R, cv::Mat T); cv::Mat RVecT2Proj(cv::Mat RVec, cv::Mat T); cv::Mat RVecT2ProjInt(cv::Mat RVec, cv::Mat T, cv::Mat K); @@ -56,4 +58,6 @@ cv::Mat convertRotationMatrixToQuaternion(cv::Mat R); cv::Mat convertQuaternionToRotationMatrix(const std::array &q); cv::Mat getAverageRotation(std::vector &r1, std::vector &r2, std::vector &r3, - const bool use_quaternion_averaging = true); \ No newline at end of file + const bool use_quaternion_averaging = true); + +} //namespace McCalib \ No newline at end of file diff --git a/McCalib/include/point_refinement.h b/McCalib/include/point_refinement.h index 6239c276..0a71a0c8 100644 --- a/McCalib/include/point_refinement.h +++ b/McCalib/include/point_refinement.h @@ -3,7 +3,7 @@ #include #include -/****** ******/ +namespace McCalib { float step_threshold = 0.001; @@ -185,3 +185,5 @@ void saddleSubpixelRefinement(const cv::Mat &input, saddleSubpixelRefinement(smooth, initial, A, valid, refined, window_half_size, max_iterations); } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Board.cpp b/McCalib/src/Board.cpp index 667dbb73..dde49110 100644 --- a/McCalib/src/Board.cpp +++ b/McCalib/src/Board.cpp @@ -10,6 +10,7 @@ #include "Frame.hpp" #include "logger.h" +namespace McCalib { /** * @brief Initialize Board object @@ -85,3 +86,5 @@ void Board::insertNewBoard(std::shared_ptr new_board) { void Board::insertNewFrame(std::shared_ptr new_frame) { frames_[new_frame->frame_idx_] = new_frame; } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/BoardObs.cpp b/McCalib/src/BoardObs.cpp index 0a32c8ea..763d6494 100644 --- a/McCalib/src/BoardObs.cpp +++ b/McCalib/src/BoardObs.cpp @@ -9,6 +9,8 @@ #include "geometrytools.hpp" #include "logger.h" +namespace McCalib { + /** * @brief Initialize the board observation object * @@ -197,3 +199,5 @@ float BoardObs::computeReprojectionError() { return (error_board_vec.size() > 0) ? sum_err_board / error_board_vec.size() : 0.f; } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Camera.cpp b/McCalib/src/Camera.cpp index 8aa49c5c..b2a51ee6 100644 --- a/McCalib/src/Camera.cpp +++ b/McCalib/src/Camera.cpp @@ -11,6 +11,8 @@ #include "OptimizationCeres.h" #include "logger.h" +namespace McCalib { + Camera::Camera(const int cam_idx, const int distortion_model) : cam_idx_(cam_idx), distortion_model_(distortion_model) {} @@ -300,3 +302,5 @@ void Camera::refineIntrinsicCalibration(const int nb_iterations) { LOG_INFO << "distortion vector after optimization :: " << getDistortionVectorVector(); } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/CameraGroup.cpp b/McCalib/src/CameraGroup.cpp index 5d7dc5a6..bdfa39fe 100644 --- a/McCalib/src/CameraGroup.cpp +++ b/McCalib/src/CameraGroup.cpp @@ -9,6 +9,8 @@ #include "CameraGroup.hpp" #include "logger.h" +namespace McCalib { + /** * @brief Initialize the camera group object * @@ -577,3 +579,5 @@ void CameraGroup::refineCameraGroupAndObjectsAndIntrinsics( LOG_INFO << "Camera " << it.first << " :: " << getCameraPoseMat(it.first); } } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/CameraGroupObs.cpp b/McCalib/src/CameraGroupObs.cpp index 5c946c6c..619cf82c 100644 --- a/McCalib/src/CameraGroupObs.cpp +++ b/McCalib/src/CameraGroupObs.cpp @@ -8,6 +8,8 @@ #include "CameraGroupObs.hpp" +namespace McCalib { + /** * @brief Associate this observation with its respective camera group * @@ -211,3 +213,5 @@ void CameraGroupObs::updateObjObsPose() { } } } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/CameraObs.cpp b/McCalib/src/CameraObs.cpp index 602837de..a592c7c6 100755 --- a/McCalib/src/CameraObs.cpp +++ b/McCalib/src/CameraObs.cpp @@ -6,6 +6,8 @@ #include "CameraObs.hpp" +namespace McCalib { + CameraObs::CameraObs(std::shared_ptr new_board) { insertNewBoard(new_board); } @@ -30,3 +32,5 @@ void CameraObs::insertNewObject(std::shared_ptr new_object) { object_observations_[object_observations_.size()] = new_object; object_idx_.push_back(new_object->object_3d_id_); } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Frame.cpp b/McCalib/src/Frame.cpp index 98ad0e48..13671b0b 100644 --- a/McCalib/src/Frame.cpp +++ b/McCalib/src/Frame.cpp @@ -6,6 +6,8 @@ #include "Frame.hpp" +namespace McCalib { + Frame::Frame(const int frame_idx, const int cam_idx, const std::string frame_path) { frame_idx_ = frame_idx; @@ -54,3 +56,5 @@ void Frame::insertNewCameraGroupObs( cam_group_idx_.push_back(camera_group_idx); cam_group_observations_[cam_group_observations_.size()] = new_cam_group_obs; } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Graph.cpp b/McCalib/src/Graph.cpp index a985791f..4982d00f 100755 --- a/McCalib/src/Graph.cpp +++ b/McCalib/src/Graph.cpp @@ -150,4 +150,4 @@ std::vector Graph::getPath(const std::vector &p_map, std::reverse(path.begin(), path.end()); // return in v1->v2 order return path; -} +} \ No newline at end of file diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 9d04d55b..2023e9a1 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -1,18 +1,18 @@ -#include "opencv2/core/core.hpp" #include -#include -#include #include #include +#include + +#include +#include +#include +#include +#include #include "McCalib.hpp" #include "logger.h" #include "point_refinement.h" -#include -#include -#include - namespace McCalib { /** @@ -114,15 +114,16 @@ Calibration::Calibration(const std::string config_path) { boards_index.resize(nb_board_); std::iota(boards_index.begin(), boards_index.end(), 0); } - std::map charuco_boards; + std::map> charuco_boards; int offset_count = 0; for (int i = 0; i <= max_board_idx; i++) { - const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::Ptr charuco = new cv::aruco::CharucoBoard( cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), length_square, length_marker, dict_); + if (i != 0) // If it is the first board then just use the standard idx { - int id_offset = charuco_boards[i - 1].getIds().size() + offset_count; + int id_offset = charuco_boards[i - 1]->getIds().size() + offset_count; offset_count = id_offset; // for (int &id : charuco.getIds()) // id += id_offset; @@ -304,14 +305,12 @@ void Calibration::detectBoardsInImageWithCamera(const std::string frame_path, charuco_params_.adaptiveThreshConstant = 1; for (std::size_t i = 0; i < nb_board_; i++) { - cv::aruco::ArucoDetector detector(boards_3d_[i]->charuco_board_.getDictionary(), charuco_params_); + cv::aruco::ArucoDetector detector(boards_3d_[i]->charuco_board_->getDictionary(), charuco_params_); detector.detectMarkers(image, marker_corners[i], marker_idx[i]); - - // cv::aruco::detectMarkers(image, dict, marker_corners[i], marker_idx[i], &charuco_params_); if (marker_corners[i].size() > 0) { cv::aruco::interpolateCornersCharuco(marker_corners[i], marker_idx[i], - image, &boards_3d_[i]->charuco_board_, + image, boards_3d_[i]->charuco_board_, charuco_corners[i], charuco_idx[i]); } diff --git a/McCalib/src/Object3D.cpp b/McCalib/src/Object3D.cpp index 9e7a3b3f..bb0802db 100644 --- a/McCalib/src/Object3D.cpp +++ b/McCalib/src/Object3D.cpp @@ -11,6 +11,8 @@ #include "geometrytools.hpp" #include "logger.h" +namespace McCalib { + /** * @brief Insert a new object observation for this 3D object * @@ -262,3 +264,5 @@ void Object3D::updateObjectPts() { } } } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Object3DObs.cpp b/McCalib/src/Object3DObs.cpp index 50cd8a3a..94f0bdb3 100644 --- a/McCalib/src/Object3DObs.cpp +++ b/McCalib/src/Object3DObs.cpp @@ -9,6 +9,8 @@ #include "geometrytools.hpp" #include "logger.h" +namespace McCalib { + /** * @brief initialize the object in the observation (what board is observed) * @@ -285,3 +287,5 @@ float Object3DObs::computeReprojectionError() const { return error_object_vec.size() > 0 ? sum_err_object / error_object_vec.size() : sum_err_object; } + +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index 23f5d00e..9b45f151 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -8,6 +8,8 @@ #include "geometrytools.hpp" #include "logger.h" +namespace McCalib { + // Tools for rotation and projection matrix cv::Mat RT2Proj(cv::Mat R, cv::Mat T) { cv::Mat Proj = (cv::Mat_(4, 4) << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, @@ -749,4 +751,6 @@ cv::Mat getAverageRotation(std::vector &r1, std::vector &r2, } return average_rotation; -} \ No newline at end of file +} + +} // namespace McCalib \ No newline at end of file diff --git a/tests/simple_unit_tests_example.cpp b/tests/simple_unit_tests_example.cpp index 74a38d14..53a5dc71 100644 --- a/tests/simple_unit_tests_example.cpp +++ b/tests/simple_unit_tests_example.cpp @@ -10,7 +10,7 @@ BOOST_AUTO_TEST_SUITE(CheckGeometryTools) BOOST_AUTO_TEST_CASE(ProjToVecAllZeros) { cv::Mat proj_matrix = (cv::Mat_(4, 4) << 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); - std::array output = ProjToVec(proj_matrix); + std::array output = McCalib::ProjToVec(proj_matrix); std::array answer = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; diff --git a/tests/test_calibration.cpp b/tests/test_calibration.cpp index 9b1ba430..5a70aa71 100644 --- a/tests/test_calibration.cpp +++ b/tests/test_calibration.cpp @@ -80,7 +80,7 @@ void calibrateAndCheckGt(std::string config_path, std::string gt_path) { camera_pose_matrix_gt = transform * camera_pose_matrix_gt * transform; double fx_gt = camera_matrix_gt.at(0, 0); - double fy_gt = camera_matrix_gt.at(1, 0); + double fy_gt = camera_matrix_gt.at(1, 1); double cx_gt = camera_matrix_gt.at(0, 2); double cy_gt = camera_matrix_gt.at(1, 2); cv::Mat rot_gt(3, 3, CV_64F); @@ -89,14 +89,14 @@ void calibrateAndCheckGt(std::string config_path, std::string gt_path) { tran_gt = camera_pose_matrix_gt(cv::Range(0, 3), cv::Range(3, 4)); // get calibrated values - std::shared_ptr cur_cam = Calib.cams_[camera_idx - 1]; + std::shared_ptr cur_cam = Calib.cams_[camera_idx - 1]; int camera_group_idx = 0; // specific to the setup with single camera group cv::Mat camera_matrix_pred = cur_cam->getCameraMat(); cv::Mat camera_pose_matrix_pred = Calib.cam_group_[camera_group_idx]->getCameraPoseMat(camera_idx - 1); double fx_pred = camera_matrix_pred.at(0, 0); - double fy_pred = camera_matrix_pred.at(1, 0); + double fy_pred = camera_matrix_pred.at(1, 1); double cx_pred = camera_matrix_pred.at(0, 2); double cy_pred = camera_matrix_pred.at(1, 2); cv::Mat rot_pred(3, 3, CV_64F); @@ -123,6 +123,11 @@ BOOST_AUTO_TEST_CASE(CheckBlenderDatasetIsPlacedCorrectly) { std::string blender_images_path = "../data/Blender_Images"; bool is_path_existent = boost::filesystem::exists(blender_images_path); BOOST_REQUIRE_EQUAL(is_path_existent, true); + + std::cout << cv::getVersionMajor() << std::endl; + std::cout << cv::getVersionMinor() << std::endl; + std::cout << cv::getVersionRevision() << std::endl; + } BOOST_AUTO_TEST_CASE(CheckCalibrationSyntheticScenario1) { diff --git a/tests/test_geometrytools.cpp b/tests/test_geometrytools.cpp index 3b4be207..aef6e1c0 100644 --- a/tests/test_geometrytools.cpp +++ b/tests/test_geometrytools.cpp @@ -9,7 +9,7 @@ double INTRINSICS_TOLERANCE = 1.0; // in percentage BOOST_AUTO_TEST_CASE(CheckRotationMatrixToQuaternionConversion1) { std::array rot_matrix_data = {1, 0, 0, 0, 1, 0, 0, 0, 1}; const cv::Mat rot_matrix = cv::Mat(3, 3, CV_64F, rot_matrix_data.data()); - const cv::Mat quaternion_pred = convertRotationMatrixToQuaternion(rot_matrix); + const cv::Mat quaternion_pred = McCalib::convertRotationMatrixToQuaternion(rot_matrix); std::array quaternion_gt_data = {0, 0, 0, 1}; const cv::Mat quaternion_gt = @@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(CheckRotationMatrixToQuaternionConversion2) { 0.1998, 0.6000, -0.8000, 0.3996, -0.8000, -0.5999}; const cv::Mat rot_matrix = cv::Mat(3, 3, CV_64F, rot_matrix_data.data()); - const cv::Mat quaternion_pred = convertRotationMatrixToQuaternion(rot_matrix); + const cv::Mat quaternion_pred = McCalib::convertRotationMatrixToQuaternion(rot_matrix); std::array quaternion_gt_data = {0, 0.8944, -0.4472, -0.2234}; // x y z w @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(CheckQuaternionToRotationMatrixConversion) { -0.2092473}; // x y z w const cv::Mat quaternion = cv::Mat(1, 4, CV_64F, quaternion_data.data()); - cv::Mat rot_matrix_pred = convertQuaternionToRotationMatrix(quaternion); + cv::Mat rot_matrix_pred = McCalib::convertQuaternionToRotationMatrix(quaternion); std::array rot_matrix_gt_data = { -0.7545152, 0.2955056, -0.5859892, 0.6460947, 0.4911810, @@ -77,9 +77,9 @@ BOOST_AUTO_TEST_CASE(CheckRotationMatrixToQuaternionAndBackConversion) { cv::Mat rot_matrix_before; cv::Rodrigues(rot_vec, rot_matrix_before); const cv::Mat quaternion = - convertRotationMatrixToQuaternion(rot_matrix_before); + McCalib::convertRotationMatrixToQuaternion(rot_matrix_before); cv::Mat rot_matrix_after = - convertQuaternionToRotationMatrix(quaternion); + McCalib::convertQuaternionToRotationMatrix(quaternion); BOOST_REQUIRE_EQUAL(rot_matrix_after.size[0], rot_matrix_before.size[0]); From a33577ce13e7165e54536689600b0f38d8bbd8ac Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Sat, 31 Aug 2024 13:33:26 +0200 Subject: [PATCH 08/17] Fixing idxs of markers on separate boards --- McCalib/include/McCalib.hpp | 7 ++-- McCalib/src/McCalib.cpp | 26 +++++++++---- .../src/create_charuco_boards.cpp | 37 ++++++++++++------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/McCalib/include/McCalib.hpp b/McCalib/include/McCalib.hpp index a5469e96..3b03dd0c 100644 --- a/McCalib/include/McCalib.hpp +++ b/McCalib/include/McCalib.hpp @@ -35,9 +35,10 @@ class Calibration final { public: // Parameters unsigned int nb_camera_, nb_board_; -cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( - cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the - // charuco board + cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( + cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the + // charuco board + cv::aruco::DetectorParameters charuco_params_ = cv::aruco::DetectorParameters(); // parameters for detection float min_perc_pts_; diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 2023e9a1..9897cbbf 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -117,18 +117,30 @@ Calibration::Calibration(const std::string config_path) { std::map> charuco_boards; int offset_count = 0; for (int i = 0; i <= max_board_idx; i++) { - cv::Ptr charuco = new cv::aruco::CharucoBoard( - cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), - length_square, length_marker, dict_); + if (i == 0) + { + // If it is the first board then just use the standard idx + cv::Ptr charuco = new cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), + length_square, length_marker, dict_); - if (i != 0) // If it is the first board then just use the standard idx + charuco_boards[i] = charuco; + } + else { int id_offset = charuco_boards[i - 1]->getIds().size() + offset_count; offset_count = id_offset; - // for (int &id : charuco.getIds()) - // id += id_offset; + const std::size_t num_idxs = charuco_boards[i - 1]->getIds().size(); + std::vector cur_ids(num_idxs); + std::iota(cur_ids.begin(), cur_ids.end(), id_offset); + + cv::Ptr charuco = new cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), + length_square, length_marker, dict_, cur_ids); + + charuco_boards[i] = charuco; } - charuco_boards[i] = charuco; + } // Initialize the 3D boards diff --git a/apps/create_charuco_boards/src/create_charuco_boards.cpp b/apps/create_charuco_boards/src/create_charuco_boards.cpp index da4fd6ba..442572b4 100644 --- a/apps/create_charuco_boards/src/create_charuco_boards.cpp +++ b/apps/create_charuco_boards/src/create_charuco_boards.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "boost/filesystem.hpp" #include @@ -60,27 +61,37 @@ int main(int argc, char *argv[]) { // Create the charuco const cv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000); - std::vector charucoBoards; + std::vector charuco_boards; int offset_count = 0; for (std::size_t i = 0; i < num_board; i++) { - // declare the board - const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( - cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), - length_square, length_marker, dict); + if (i == 0) + { + // if it is the first board then just use the standard idx + const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), + length_square, length_marker, dict); - // If it is the first board then just use the standard idx - if (i != 0) { - int id_offset = charucoBoards[i - 1].getIds().size() + offset_count; + charuco_boards.push_back(charuco); + } + else + { + int id_offset = charuco_boards[i - 1].getIds().size() + offset_count; offset_count = id_offset; - // for (auto &id : charuco->getIds()) { - // id += id_offset; - // } + + const std::size_t num_idxs = charuco_boards[i - 1].getIds().size(); + std::vector cur_ids(num_idxs); + std::iota(cur_ids.begin(), cur_ids.end(), id_offset); + + cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), + length_square, length_marker, dict, cur_ids); + + charuco_boards.push_back(charuco); } // create the charuco board - charucoBoards.push_back(charuco); cv::Mat boardImage; - charucoBoards[i].generateImage( + charuco_boards[i].generateImage( cv::Size(resolution_x_per_board[i], resolution_y_per_board[i]), boardImage, 10, 1); // Display marker From 68390955bc7a7024488886c4c8f50c1c2eacf8d5 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Mon, 2 Sep 2024 21:47:42 +0200 Subject: [PATCH 09/17] Fix linters --- McCalib/include/Board.hpp | 2 +- McCalib/include/BoardObs.hpp | 2 +- McCalib/include/Graph.hpp | 1 - McCalib/include/McCalib.hpp | 7 +++-- McCalib/include/geometrytools.hpp | 2 +- McCalib/src/Camera.cpp | 6 ++-- McCalib/src/McCalib.cpp | 29 +++++++++---------- McCalib/src/geometrytools.cpp | 4 +-- .../src/create_charuco_boards.cpp | 14 ++++----- tests/test_calibration.cpp | 1 - tests/test_geometrytools.cpp | 9 ++++-- 11 files changed, 38 insertions(+), 39 deletions(-) diff --git a/McCalib/include/Board.hpp b/McCalib/include/Board.hpp index 9e8d8ed1..7fc2f003 100644 --- a/McCalib/include/Board.hpp +++ b/McCalib/include/Board.hpp @@ -52,4 +52,4 @@ class Board final { void insertNewFrame(std::shared_ptr new_frame); }; -} //namespace McCalib +} // namespace McCalib diff --git a/McCalib/include/BoardObs.hpp b/McCalib/include/BoardObs.hpp index 0ae171b8..0a4c4726 100644 --- a/McCalib/include/BoardObs.hpp +++ b/McCalib/include/BoardObs.hpp @@ -63,4 +63,4 @@ class BoardObs final { cv::Mat getTransVec() const; }; -} //namespace McCalib \ No newline at end of file +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/include/Graph.hpp b/McCalib/include/Graph.hpp index 3b148ebb..eb94d583 100644 --- a/McCalib/include/Graph.hpp +++ b/McCalib/include/Graph.hpp @@ -5,7 +5,6 @@ #include #include - /** * @class Graph * diff --git a/McCalib/include/McCalib.hpp b/McCalib/include/McCalib.hpp index 3b03dd0c..11856d80 100644 --- a/McCalib/include/McCalib.hpp +++ b/McCalib/include/McCalib.hpp @@ -36,10 +36,11 @@ class Calibration final { // Parameters unsigned int nb_camera_, nb_board_; cv::aruco::Dictionary dict_ = cv::aruco::getPredefinedDictionary( - cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the - // charuco board + cv::aruco::DICT_6X6_1000); // load the dictionary that correspond to the + // charuco board - cv::aruco::DetectorParameters charuco_params_ = cv::aruco::DetectorParameters(); // parameters for detection + cv::aruco::DetectorParameters charuco_params_ = + cv::aruco::DetectorParameters(); // parameters for detection float min_perc_pts_; // images path diff --git a/McCalib/include/geometrytools.hpp b/McCalib/include/geometrytools.hpp index a8b24005..8981fc01 100644 --- a/McCalib/include/geometrytools.hpp +++ b/McCalib/include/geometrytools.hpp @@ -60,4 +60,4 @@ cv::Mat getAverageRotation(std::vector &r1, std::vector &r2, std::vector &r3, const bool use_quaternion_averaging = true); -} //namespace McCalib \ No newline at end of file +} // namespace McCalib \ No newline at end of file diff --git a/McCalib/src/Camera.cpp b/McCalib/src/Camera.cpp index b2a51ee6..268835a5 100644 --- a/McCalib/src/Camera.cpp +++ b/McCalib/src/Camera.cpp @@ -1,11 +1,11 @@ -#include -#include #include +#include #include +#include -#include #include "opencv2/core/core.hpp" #include +#include #include "Camera.hpp" #include "OptimizationCeres.h" diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 9897cbbf..7faab6f7 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -3,11 +3,11 @@ #include #include -#include -#include -#include #include #include +#include +#include +#include #include "McCalib.hpp" #include "logger.h" @@ -117,17 +117,15 @@ Calibration::Calibration(const std::string config_path) { std::map> charuco_boards; int offset_count = 0; for (int i = 0; i <= max_board_idx; i++) { - if (i == 0) - { + if (i == 0) { // If it is the first board then just use the standard idx - cv::Ptr charuco = new cv::aruco::CharucoBoard( - cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), - length_square, length_marker, dict_); + cv::Ptr charuco = + new cv::aruco::CharucoBoard(cv::Size(number_x_square_per_board_[i], + number_y_square_per_board_[i]), + length_square, length_marker, dict_); charuco_boards[i] = charuco; - } - else - { + } else { int id_offset = charuco_boards[i - 1]->getIds().size() + offset_count; offset_count = id_offset; const std::size_t num_idxs = charuco_boards[i - 1]->getIds().size(); @@ -135,12 +133,12 @@ Calibration::Calibration(const std::string config_path) { std::iota(cur_ids.begin(), cur_ids.end(), id_offset); cv::Ptr charuco = new cv::aruco::CharucoBoard( - cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), + cv::Size(number_x_square_per_board_[i], + number_y_square_per_board_[i]), length_square, length_marker, dict_, cur_ids); charuco_boards[i] = charuco; } - } // Initialize the 3D boards @@ -316,8 +314,9 @@ void Calibration::detectBoardsInImageWithCamera(const std::string frame_path, charuco_params_.adaptiveThreshConstant = 1; - for (std::size_t i = 0; i < nb_board_; i++) { - cv::aruco::ArucoDetector detector(boards_3d_[i]->charuco_board_->getDictionary(), charuco_params_); + for (std::size_t i = 0; i < nb_board_; i++) { + cv::aruco::ArucoDetector detector( + boards_3d_[i]->charuco_board_->getDictionary(), charuco_params_); detector.detectMarkers(image, marker_corners[i], marker_idx[i]); if (marker_corners[i].size() > 0) { diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index 9b45f151..e3056b62 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -1,9 +1,9 @@ #include "opencv2/core/core.hpp" +#include #include #include -#include -#include #include +#include #include "geometrytools.hpp" #include "logger.h" diff --git a/apps/create_charuco_boards/src/create_charuco_boards.cpp b/apps/create_charuco_boards/src/create_charuco_boards.cpp index 442572b4..a62cf24e 100644 --- a/apps/create_charuco_boards/src/create_charuco_boards.cpp +++ b/apps/create_charuco_boards/src/create_charuco_boards.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include "boost/filesystem.hpp" #include @@ -60,21 +60,19 @@ int main(int argc, char *argv[]) { } // Create the charuco - const cv::aruco::Dictionary dict = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000); + const cv::aruco::Dictionary dict = + cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_1000); std::vector charuco_boards; int offset_count = 0; for (std::size_t i = 0; i < num_board; i++) { - if (i == 0) - { + if (i == 0) { // if it is the first board then just use the standard idx const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), length_square, length_marker, dict); charuco_boards.push_back(charuco); - } - else - { + } else { int id_offset = charuco_boards[i - 1].getIds().size() + offset_count; offset_count = id_offset; @@ -88,7 +86,7 @@ int main(int argc, char *argv[]) { charuco_boards.push_back(charuco); } - + // create the charuco board cv::Mat boardImage; charuco_boards[i].generateImage( diff --git a/tests/test_calibration.cpp b/tests/test_calibration.cpp index 5a70aa71..d90101d5 100644 --- a/tests/test_calibration.cpp +++ b/tests/test_calibration.cpp @@ -127,7 +127,6 @@ BOOST_AUTO_TEST_CASE(CheckBlenderDatasetIsPlacedCorrectly) { std::cout << cv::getVersionMajor() << std::endl; std::cout << cv::getVersionMinor() << std::endl; std::cout << cv::getVersionRevision() << std::endl; - } BOOST_AUTO_TEST_CASE(CheckCalibrationSyntheticScenario1) { diff --git a/tests/test_geometrytools.cpp b/tests/test_geometrytools.cpp index aef6e1c0..e6c0ea79 100644 --- a/tests/test_geometrytools.cpp +++ b/tests/test_geometrytools.cpp @@ -9,7 +9,8 @@ double INTRINSICS_TOLERANCE = 1.0; // in percentage BOOST_AUTO_TEST_CASE(CheckRotationMatrixToQuaternionConversion1) { std::array rot_matrix_data = {1, 0, 0, 0, 1, 0, 0, 0, 1}; const cv::Mat rot_matrix = cv::Mat(3, 3, CV_64F, rot_matrix_data.data()); - const cv::Mat quaternion_pred = McCalib::convertRotationMatrixToQuaternion(rot_matrix); + const cv::Mat quaternion_pred = + McCalib::convertRotationMatrixToQuaternion(rot_matrix); std::array quaternion_gt_data = {0, 0, 0, 1}; const cv::Mat quaternion_gt = @@ -28,7 +29,8 @@ BOOST_AUTO_TEST_CASE(CheckRotationMatrixToQuaternionConversion2) { 0.1998, 0.6000, -0.8000, 0.3996, -0.8000, -0.5999}; const cv::Mat rot_matrix = cv::Mat(3, 3, CV_64F, rot_matrix_data.data()); - const cv::Mat quaternion_pred = McCalib::convertRotationMatrixToQuaternion(rot_matrix); + const cv::Mat quaternion_pred = + McCalib::convertRotationMatrixToQuaternion(rot_matrix); std::array quaternion_gt_data = {0, 0.8944, -0.4472, -0.2234}; // x y z w @@ -48,7 +50,8 @@ BOOST_AUTO_TEST_CASE(CheckQuaternionToRotationMatrixConversion) { -0.2092473}; // x y z w const cv::Mat quaternion = cv::Mat(1, 4, CV_64F, quaternion_data.data()); - cv::Mat rot_matrix_pred = McCalib::convertQuaternionToRotationMatrix(quaternion); + cv::Mat rot_matrix_pred = + McCalib::convertQuaternionToRotationMatrix(quaternion); std::array rot_matrix_gt_data = { -0.7545152, 0.2955056, -0.5859892, 0.6460947, 0.4911810, From 46d6916423584ad2f5842c71b687806c72da3ab0 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 3 Sep 2024 07:22:32 +0200 Subject: [PATCH 10/17] Update to opencv410 docker --- .github/workflows/main.yml | 16 ++++++++-------- README.md | 4 ++-- docs/Documentation.md | 2 +- docs/Windows.md | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e3ae3bd5..e698824d 100755 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: - name: Run cppcheck uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib run: | cppcheck MC-Calib/McCalib/include @@ -58,7 +58,7 @@ jobs: - name: Run clang-tidy uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib run: | mkdir MC-Calib/build && cd MC-Calib/build @@ -90,7 +90,7 @@ jobs: - name: Run tests uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib run: | mkdir MC-Calib/build && cd MC-Calib/build @@ -122,7 +122,7 @@ jobs: - name: Run tests uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib run: | mkdir MC-Calib/build && cd MC-Calib/build @@ -165,7 +165,7 @@ jobs: - name: Run tests uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-prod:latest + image: bailool/mc-calib-prod:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib:rw run: | mkdir MC-Calib/build && cd MC-Calib/build @@ -228,7 +228,7 @@ jobs: - name: Run tests uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:${{ github.workspace }} run: | mkdir ${{ github.workspace }}/build && cd ${{ github.workspace }}/build @@ -266,7 +266,7 @@ jobs: - name: Run python linters uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-dev:latest + image: bailool/mc-calib-dev:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib run: | cd MC-Calib/python_utils @@ -292,7 +292,7 @@ jobs: - name: Run python utils uses: addnab/docker-run-action@v3 with: - image: bailool/mc-calib-prod:latest + image: bailool/mc-calib-prod:opencv410 options: -v ${{ github.workspace }}:/home/MC-Calib:rw run: | cd MC-Calib/python_utils diff --git a/README.md b/README.md index edbe3643..fdc331d4 100755 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ There are several ways to get the environment ready. Choose any of them: - Pull the image: ```bash - docker pull bailool/mc-calib-prod # production environment - docker pull bailool/mc-calib-dev # development environment + docker pull bailool/mc-calib-prod:opencv410 # production environment + docker pull bailool/mc-calib-dev:opencv410 # development environment ``` - Run pulled image (set `PATH_TO_REPO_ROOT` and `PATH_TO_DATA` appropriately): diff --git a/docs/Documentation.md b/docs/Documentation.md index fa463350..7881013d 100644 --- a/docs/Documentation.md +++ b/docs/Documentation.md @@ -4,7 +4,7 @@ - It is also possible to generate Doxygen documentation locally: - - Install [Doxygen](https://www.doxygen.nl/download.html) or use `bailool/mc-calib-dev` docker image: + - Install [Doxygen](https://www.doxygen.nl/download.html) or use `bailool/mc-calib-dev:opencv410` docker image: ```bash sudo apt install flex diff --git a/docs/Windows.md b/docs/Windows.md index c62fe8c3..90a57b65 100644 --- a/docs/Windows.md +++ b/docs/Windows.md @@ -28,8 +28,8 @@ This documentation is meant to guide the installation of the MC-Calib toolbox, s Then pull the docker image using either one of the commands given below. ```bash -docker pull bailool/mc-calib-prod # production environment -docker pull bailool/mc-calib-dev # development environment +docker pull bailool/mc-calib-prod:opencv410 # production environment +docker pull bailool/mc-calib-dev:opencv410 # development environment ``` 4. **Running Pulled Image using Docker** @@ -41,7 +41,7 @@ Docker run ` -ti --rm ` --volume=”$PATH_TO_REPO_ROOT:/home/MC-Calib” ` --volume=”$PATH_TO_DATA:/home/MC-Calib/data” ` - bailool/mc-calib-prod + bailool/mc-calib-prod:opencv410 ``` ### User Personalization From af6109408635be75f883a7ea82314c8ec062e8ec Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 3 Sep 2024 23:15:09 +0200 Subject: [PATCH 11/17] WIP: refactoring hand-eye calibration --- McCalib/include/geometrytools.hpp | 12 +++--- McCalib/src/McCalib.cpp | 5 ++- McCalib/src/geometrytools.cpp | 64 ++++++++++++++++++------------- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/McCalib/include/geometrytools.hpp b/McCalib/include/geometrytools.hpp index 8981fc01..03fd6244 100644 --- a/McCalib/include/geometrytools.hpp +++ b/McCalib/include/geometrytools.hpp @@ -35,11 +35,13 @@ cv::Mat ransacP3P(const std::vector &scene_points, const double p = 0.99, bool refine = true); std::vector transform3DPts(std::vector pts3D, cv::Mat rot, cv::Mat trans); -cv::Mat handeyeCalibration(std::vector pose_abs_1, - std::vector pose_abs_2); -cv::Mat handeyeBootstratpTranslationCalibration( - unsigned int nb_cluster, unsigned int nb_it, - std::vector pose_abs_1, std::vector pose_abs_2); +cv::Mat handeyeCalibration(const std::vector &pose_abs_1, + const std::vector &pose_abs_2); +cv::Mat +handeyeBootstratpTranslationCalibration(const unsigned int nb_cluster, + const unsigned int nb_it, + const std::vector &pose_abs_1, + const std::vector &pose_abs_2); double median(std::vector &v); cv::Mat ransacP3PDistortion(const std::vector &scene_points, const std::vector &image_points, diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 7faab6f7..595ee754 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -1467,8 +1467,9 @@ void Calibration::initNonOverlapPair(const int cam_group_id1, cv::Mat pose_g1_g2; if (he_approach_ == 0) { // Boot strapping technique - int nb_cluster = 20; - int nb_it_he = 200; // Nb of time we apply the handeye calibration + const unsigned int nb_cluster = 20u; + const unsigned int nb_it_he = + 200u; // Nb of time we apply the handeye calibration pose_g1_g2 = handeyeBootstratpTranslationCalibration( nb_cluster, nb_it_he, pose_abs_1, pose_abs_2); } else { diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index e3056b62..a3cdc62b 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -357,14 +357,14 @@ std::vector transform3DPts(std::vector pts3D, * */ -cv::Mat handeyeCalibration(const std::vector pose_abs_1, - const std::vector pose_abs_2) { +cv::Mat handeyeCalibration(const std::vector &pose_abs_1, + const std::vector &pose_abs_2) { // Prepare the poses for handeye calibration - const size_t num_poses = pose_abs_1.size(); + const size_t num_poses = std::min(pose_abs_1.size(), pose_abs_2.size()); std::vector r_cam_group_1(num_poses), t_cam_group_1(num_poses), r_cam_group_2(num_poses), t_cam_group_2(num_poses); - for (size_t i = 0; i < num_poses; i++) { + for (std::size_t i = 0; i < num_poses; i++) { // get the poses cv::Mat pose_cam_group_1 = pose_abs_1[i].inv(); cv::Mat pose_cam_group_2 = pose_abs_2[i]; @@ -393,26 +393,15 @@ cv::Mat handeyeCalibration(const std::vector pose_abs_1, } /** - * @brief Calibrate 2 cameras with handeye calibration + * @brief Prepare the translational component of the cameras to be clustered * - * In this function only N pairs of images are used - * These pair of images are selected with a clustering technique - * The clustering is achieved via the translation of cameras - * The process is repeated multiple time on subset of the poses - * A test of consistency is performed, all potentially valid poses are saved - * The mean value of valid poses is returned */ -cv::Mat handeyeBootstratpTranslationCalibration( - unsigned int nb_cluster, unsigned int nb_it, - std::vector pose_abs_1, std::vector pose_abs_2) { - // N clusters but less if less images available - nb_cluster = - (pose_abs_1.size() < nb_cluster) ? pose_abs_1.size() : nb_cluster; - - // Prepare the translational component of the cameras to be clustered - cv::Mat position_1_2; // concatenation of the translation of pose 1 and 2 for - // clustering - for (unsigned int i = 0; i < pose_abs_1.size(); i++) { +cv::Mat getTranslationsForClustering(const std::vector &pose_abs_1, + const std::vector &pose_abs_2) { + const std::size_t num_poses = std::min(pose_abs_1.size(), pose_abs_2.size()); + + cv::Mat position_1_2; + for (std::size_t i = 0u; i < num_poses; i++) { cv::Mat trans_1, trans_2, rot_1, rot_2; Proj2RT(pose_abs_1[i], rot_1, trans_1); Proj2RT(pose_abs_2[i], rot_2, trans_2); @@ -421,13 +410,36 @@ cv::Mat handeyeBootstratpTranslationCalibration( position_1_2.push_back(concat_trans_1_2); } position_1_2.convertTo(position_1_2, CV_32F); + return position_1_2; +} + +/** + * @brief Calibrate 2 cameras with handeye calibration + * + * In this function only N pairs of images are used + * These pair of images are selected with a clustering technique + * The clustering is achieved via the translation of cameras + * The process is repeated multiple time on subset of the poses + * A test of consistency is performed, all potentially valid poses are saved + * The mean value of valid poses is returned + */ +cv::Mat handeyeBootstratpTranslationCalibration( + const unsigned int nb_cluster, const unsigned int nb_it, + const std::vector &pose_abs_1, + const std::vector &pose_abs_2) { + + // concat of the translation of pose 1 and 2 for clustering + cv::Mat position_1_2 = getTranslationsForClustering(pose_abs_1, pose_abs_2); // Cluster the observation to select the most diverse poses + const unsigned int num_clusters = + std::min(nb_cluster, static_cast( + std::min(pose_abs_1.size(), pose_abs_2.size()))); cv::Mat labels; cv::Mat centers; int nb_kmean_iterations = 5; std::ignore = - cv::kmeans(position_1_2, nb_cluster, labels, + cv::kmeans(position_1_2, num_clusters, labels, cv::TermCriteria( cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 0.01), nb_kmean_iterations, cv::KMEANS_PP_CENTERS, centers); @@ -436,12 +448,11 @@ cv::Mat handeyeBootstratpTranslationCalibration( // Iterate n times the std::vector r1_he, r2_he, r3_he; // structure to save valid rot std::vector t1_he, t2_he, t3_he; // structure to save valid trans - unsigned int nb_clust_pick = 6; + const unsigned int nb_clust_pick = 6; unsigned int nb_success = 0; for (unsigned int iter = 0; iter < nb_it; iter++) { - // pick from n of these clusters randomly - std::vector shuffled_ind(nb_cluster); + std::vector shuffled_ind(num_clusters); std::iota(shuffled_ind.begin(), shuffled_ind.end(), 0); std::random_device rd; // initialize random number generator std::mt19937 g(rd()); @@ -463,7 +474,6 @@ cv::Mat handeyeBootstratpTranslationCalibration( } } // randomly select an index in the occurrences of the cluster - srand(time(NULL)); std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> dis(0, idx.size() - 1); From fa3fa50e984f81aa03f935ccb334ce94cfdec14a Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Wed, 4 Sep 2024 23:09:32 +0200 Subject: [PATCH 12/17] Refactor clustering of translations --- McCalib/src/McCalib.cpp | 6 +++--- McCalib/src/geometrytools.cpp | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index 595ee754..b339ce89 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -1466,10 +1466,10 @@ void Calibration::initNonOverlapPair(const int cam_group_id1, // HANDEYE CALIBRATION cv::Mat pose_g1_g2; if (he_approach_ == 0) { - // Boot strapping technique + // Bootstrapping technique const unsigned int nb_cluster = 20u; - const unsigned int nb_it_he = - 200u; // Nb of time we apply the handeye calibration + // number of iterations of handeye calibration + const unsigned int nb_it_he = 200u; pose_g1_g2 = handeyeBootstratpTranslationCalibration( nb_cluster, nb_it_he, pose_abs_1, pose_abs_2); } else { diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index a3cdc62b..2e7a060a 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -413,6 +413,20 @@ cv::Mat getTranslationsForClustering(const std::vector &pose_abs_1, return position_1_2; } +cv::Mat clusterTranslations(const cv::Mat &position_1_2, + const unsigned int num_clusters) { + const unsigned int nb_kmean_iterations = 5; + cv::Mat labels; + cv::Mat centers; + std::ignore = + cv::kmeans(position_1_2, num_clusters, labels, + cv::TermCriteria( + cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 0.01), + nb_kmean_iterations, cv::KMEANS_PP_CENTERS, centers); + labels.convertTo(labels, CV_32S); + return labels; +} + /** * @brief Calibrate 2 cameras with handeye calibration * @@ -435,15 +449,7 @@ cv::Mat handeyeBootstratpTranslationCalibration( const unsigned int num_clusters = std::min(nb_cluster, static_cast( std::min(pose_abs_1.size(), pose_abs_2.size()))); - cv::Mat labels; - cv::Mat centers; - int nb_kmean_iterations = 5; - std::ignore = - cv::kmeans(position_1_2, num_clusters, labels, - cv::TermCriteria( - cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 0.01), - nb_kmean_iterations, cv::KMEANS_PP_CENTERS, centers); - labels.convertTo(labels, CV_32S); + const cv::Mat labels = clusterTranslations(position_1_2, num_clusters); // Iterate n times the std::vector r1_he, r2_he, r3_he; // structure to save valid rot From 179bed54c9b5eea6af336ec0fa1c2a836fcf956e Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Thu, 5 Sep 2024 22:55:53 +0200 Subject: [PATCH 13/17] Refactor random selection of poses from clusters --- McCalib/src/geometrytools.cpp | 112 +++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 44 deletions(-) diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index 2e7a060a..a6f88dae 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -397,9 +397,8 @@ cv::Mat handeyeCalibration(const std::vector &pose_abs_1, * */ cv::Mat getTranslationsForClustering(const std::vector &pose_abs_1, - const std::vector &pose_abs_2) { - const std::size_t num_poses = std::min(pose_abs_1.size(), pose_abs_2.size()); - + const std::vector &pose_abs_2, + const std::size_t num_poses) { cv::Mat position_1_2; for (std::size_t i = 0u; i < num_poses; i++) { cv::Mat trans_1, trans_2, rot_1, rot_2; @@ -427,6 +426,52 @@ cv::Mat clusterTranslations(const cv::Mat &position_1_2, return labels; } +std::vector selectClusters(const unsigned int num_clusters, + const unsigned int nb_clust_pick) { + // pick from n clusters randomly + std::vector shuffled_ind(num_clusters); + std::iota(shuffled_ind.begin(), shuffled_ind.end(), 0); + assert(shuffled_ind.size() == num_clusters); + + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(shuffled_ind.begin(), shuffled_ind.end(), g); + std::vector cluster_select; + cluster_select.reserve(nb_clust_pick); + for (unsigned int k = 0; k < nb_clust_pick; ++k) { + cluster_select.push_back(shuffled_ind[k]); + } + + assert(cluster_select.size() == nb_clust_pick); + return cluster_select; +} + +std::vector +selectPoses(const cv::Mat &clusters_lables, + const std::vector &selected_cluster_idxs, + const unsigned int num_poses) { + // Select one pair of pose (indexes) from each cluster + std::vector selected_poses_idxs; + selected_poses_idxs.reserve(selected_cluster_idxs.size()); + for (const unsigned int cluster_idx : selected_cluster_idxs) { + std::vector pose_idxs; + for (unsigned int pose_idx = 0u; pose_idx < num_poses; pose_idx++) { + if (clusters_lables.at(pose_idx) == cluster_idx) { + pose_idxs.push_back(pose_idx); + } + } + // randomly select an index in the occurrences of the cluster + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0, pose_idxs.size() - 1); + unsigned int random_idx = dis(gen); + selected_poses_idxs.push_back(pose_idxs[random_idx]); + } + + assert(selected_poses_idxs.size() == selected_cluster_idxs.size()); + return selected_poses_idxs; +} + /** * @brief Calibrate 2 cameras with handeye calibration * @@ -443,13 +488,16 @@ cv::Mat handeyeBootstratpTranslationCalibration( const std::vector &pose_abs_2) { // concat of the translation of pose 1 and 2 for clustering - cv::Mat position_1_2 = getTranslationsForClustering(pose_abs_1, pose_abs_2); + const std::size_t num_poses = std::min(pose_abs_1.size(), pose_abs_2.size()); + cv::Mat position_1_2 = + getTranslationsForClustering(pose_abs_1, pose_abs_2, num_poses); // Cluster the observation to select the most diverse poses const unsigned int num_clusters = std::min(nb_cluster, static_cast( std::min(pose_abs_1.size(), pose_abs_2.size()))); - const cv::Mat labels = clusterTranslations(position_1_2, num_clusters); + const cv::Mat clusters_lables = + clusterTranslations(position_1_2, num_clusters); // Iterate n times the std::vector r1_he, r2_he, r3_he; // structure to save valid rot @@ -457,44 +505,20 @@ cv::Mat handeyeBootstratpTranslationCalibration( const unsigned int nb_clust_pick = 6; unsigned int nb_success = 0; for (unsigned int iter = 0; iter < nb_it; iter++) { - // pick from n of these clusters randomly - std::vector shuffled_ind(num_clusters); - std::iota(shuffled_ind.begin(), shuffled_ind.end(), 0); - std::random_device rd; // initialize random number generator - std::mt19937 g(rd()); - std::shuffle(shuffled_ind.begin(), shuffled_ind.end(), g); - std::vector cluster_select; - cluster_select.reserve(nb_clust_pick); - for (unsigned int k = 0; k < nb_clust_pick; ++k) { - cluster_select.push_back(shuffled_ind[k]); - } + const std::vector selected_cluster_idxs = + selectClusters(num_clusters, nb_clust_pick); - // Select one pair of pose for each cluster - std::vector pose_ind; - pose_ind.reserve(cluster_select.size()); - for (const unsigned int &clust_ind : cluster_select) { - std::vector idx; - for (unsigned int j = 0; j < pose_abs_2.size(); j++) { - if (labels.at(j) == clust_ind) { - idx.push_back(j); - } - } - // randomly select an index in the occurrences of the cluster - std::random_device rd; - std::mt19937 gen(rd()); - std::uniform_int_distribution<> dis(0, idx.size() - 1); - unsigned int cluster_idx = dis(gen); - pose_ind.push_back(idx[cluster_idx]); - } + const std::vector selected_poses_idxs = + selectPoses(clusters_lables, selected_cluster_idxs, num_poses); // Prepare the poses for handeye calibration std::vector r_cam_group_1, t_cam_group_1, r_cam_group_2, t_cam_group_2; - r_cam_group_1.reserve(pose_ind.size()); - t_cam_group_1.reserve(pose_ind.size()); - r_cam_group_2.reserve(pose_ind.size()); - t_cam_group_2.reserve(pose_ind.size()); - for (const auto &pose_ind_i : pose_ind) { + r_cam_group_1.reserve(nb_clust_pick); + t_cam_group_1.reserve(nb_clust_pick); + r_cam_group_2.reserve(nb_clust_pick); + t_cam_group_2.reserve(nb_clust_pick); + for (const auto &pose_ind_i : selected_poses_idxs) { // get the poses cv::Mat pose_cam_group_1 = pose_abs_1[pose_ind_i].inv(); cv::Mat pose_cam_group_2 = pose_abs_2[pose_ind_i]; @@ -522,13 +546,13 @@ cv::Mat handeyeBootstratpTranslationCalibration( // Check the consistency of the set double max_error = 0; - for (unsigned int i = 0; i < pose_ind.size(); i++) { - cv::Mat pose_cam_group_1_1 = pose_abs_1[pose_ind[i]]; - cv::Mat pose_cam_group_2_1 = pose_abs_2[pose_ind[i]]; - for (unsigned int j = 0; j < pose_ind.size(); j++) { + for (unsigned int i = 0; i < selected_poses_idxs.size(); i++) { + cv::Mat pose_cam_group_1_1 = pose_abs_1[selected_poses_idxs[i]]; + cv::Mat pose_cam_group_2_1 = pose_abs_2[selected_poses_idxs[i]]; + for (unsigned int j = 0; j < selected_poses_idxs.size(); j++) { if (i != j) { - cv::Mat pose_cam_group_1_2 = pose_abs_1[pose_ind[i]]; - cv::Mat pose_cam_group_2_2 = pose_abs_2[pose_ind[i]]; + cv::Mat pose_cam_group_1_2 = pose_abs_1[selected_poses_idxs[i]]; + cv::Mat pose_cam_group_2_2 = pose_abs_2[selected_poses_idxs[i]]; cv::Mat PP1 = pose_cam_group_1_2.inv() * pose_cam_group_1_1; cv::Mat PP2 = pose_cam_group_2_1.inv() * pose_cam_group_2_2; cv::Mat ErrMat = PP2.inv() * pose_g1_g2 * PP1 * pose_g1_g2; From bddbb2f7ddd160a02c9c915580796a85fe7cd463 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 10 Sep 2024 22:16:33 +0200 Subject: [PATCH 14/17] Refactor preparePosesForHandEyeCalibration() --- McCalib/src/geometrytools.cpp | 55 +++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index a6f88dae..f594dba9 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -472,6 +472,36 @@ selectPoses(const cv::Mat &clusters_lables, return selected_poses_idxs; } +void preparePosesForHandEyeCalibration( + const std::vector &pose_abs_1, + const std::vector &pose_abs_2, + const std::vector &selected_poses_idxs, + std::vector &r_cam_group_1, std::vector &t_cam_group_1, + std::vector &r_cam_group_2, std::vector &t_cam_group_2) { + const std::size_t nb_clust_pick = selected_poses_idxs.size(); + r_cam_group_1.reserve(nb_clust_pick); + t_cam_group_1.reserve(nb_clust_pick); + r_cam_group_2.reserve(nb_clust_pick); + t_cam_group_2.reserve(nb_clust_pick); + for (const unsigned int pose_ind_i : selected_poses_idxs) { + // get the poses + const cv::Mat pose_cam_group_1 = pose_abs_1[pose_ind_i].inv(); + const cv::Mat pose_cam_group_2 = pose_abs_2[pose_ind_i]; + + // save in datastruct + cv::Mat r_1, r_2, t_1, t_2; + Proj2RT(pose_cam_group_1, r_1, t_1); + Proj2RT(pose_cam_group_2, r_2, t_2); + cv::Mat r_1_mat, r_2_mat; + cv::Rodrigues(r_1, r_1_mat); + cv::Rodrigues(r_2, r_2_mat); + r_cam_group_1.push_back(r_1_mat); + t_cam_group_1.push_back(t_1); + r_cam_group_2.push_back(r_2_mat); + t_cam_group_2.push_back(t_2); + } +} + /** * @brief Calibrate 2 cameras with handeye calibration * @@ -514,34 +544,15 @@ cv::Mat handeyeBootstratpTranslationCalibration( // Prepare the poses for handeye calibration std::vector r_cam_group_1, t_cam_group_1, r_cam_group_2, t_cam_group_2; - r_cam_group_1.reserve(nb_clust_pick); - t_cam_group_1.reserve(nb_clust_pick); - r_cam_group_2.reserve(nb_clust_pick); - t_cam_group_2.reserve(nb_clust_pick); - for (const auto &pose_ind_i : selected_poses_idxs) { - // get the poses - cv::Mat pose_cam_group_1 = pose_abs_1[pose_ind_i].inv(); - cv::Mat pose_cam_group_2 = pose_abs_2[pose_ind_i]; - - // save in datastruct - cv::Mat r_1, r_2, t_1, t_2; - Proj2RT(pose_cam_group_1, r_1, t_1); - Proj2RT(pose_cam_group_2, r_2, t_2); - cv::Mat r_1_mat, r_2_mat; - cv::Rodrigues(r_1, r_1_mat); - cv::Rodrigues(r_2, r_2_mat); - r_cam_group_1.push_back(r_1_mat); - t_cam_group_1.push_back(t_1); - r_cam_group_2.push_back(r_2_mat); - t_cam_group_2.push_back(t_2); - } + preparePosesForHandEyeCalibration( + pose_abs_1, pose_abs_2, selected_poses_idxs, r_cam_group_1, + t_cam_group_1, r_cam_group_2, t_cam_group_2); // Hand-eye calibration cv::Mat r_g1_g2, t_g1_g2; cv::calibrateHandEye(r_cam_group_1, t_cam_group_1, r_cam_group_2, t_cam_group_2, r_g1_g2, t_g1_g2, cv::CALIB_HAND_EYE_TSAI); - // cv::CALIB_HAN cv::Mat pose_g1_g2 = RT2Proj(r_g1_g2, t_g1_g2); // Check the consistency of the set From a3b2ef2a04c641d7551b844934ac3b3e74b14a16 Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 10 Sep 2024 22:59:24 +0200 Subject: [PATCH 15/17] Minor refactoring and log message --- McCalib/src/geometrytools.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/McCalib/src/geometrytools.cpp b/McCalib/src/geometrytools.cpp index f594dba9..1299dbee 100644 --- a/McCalib/src/geometrytools.cpp +++ b/McCalib/src/geometrytools.cpp @@ -574,14 +574,13 @@ cv::Mat handeyeBootstratpTranslationCalibration( double traceRot = cv::trace(ErrRotMat)[0] - std::numeric_limits::epsilon(); double err_degree = std::acos(0.5 * (traceRot - 1.0)) * 180.0 / M_PI; - if (err_degree > max_error) - max_error = err_degree; + max_error = std::max(max_error, err_degree); } } } if (max_error < 15) { nb_success++; - // if it is a sucess then add to our valid pose evector + // if it is a sucess then add to our valid pose vector cv::Mat rot_temp, trans_temp; Proj2RT(pose_g1_g2, rot_temp, trans_temp); r1_he.push_back(rot_temp.at(0)); @@ -602,8 +601,8 @@ cv::Mat handeyeBootstratpTranslationCalibration( t_he.at(2) = median(t3_he); cv::Mat pose_g1_g2 = RVecT2Proj(r_he, t_he); return pose_g1_g2; - } else // else run the normal handeye calibration on all the samples - { + } else { + LOG_DEBUG << "Run the normal handeye calibration on all the samples"; cv::Mat pose_g1_g2 = handeyeCalibration(pose_abs_1, pose_abs_1); return pose_g1_g2; } @@ -611,9 +610,12 @@ cv::Mat handeyeBootstratpTranslationCalibration( // median of the vector but modifies original vector double median(std::vector &v) { - size_t n = v.size() / 2; - std::nth_element(v.begin(), v.begin() + n, v.end()); - return v[n]; + const std::size_t n_elements = v.size(); + if (n_elements == 0) + return 0.f; + std::sort(v.begin(), v.end()); + const std::size_t mid = n_elements / 2; + return n_elements % 2 == 0 ? (v[mid] + v[mid - 1]) / 2 : v[mid]; } // RANSAC algorithm From 7008c994dbfb0fa09b35f72ddc8f2c6daa6d1e3e Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 10 Sep 2024 23:09:08 +0200 Subject: [PATCH 16/17] Upgrade clang-format-lint-action version --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e698824d..351291b6 100755 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,7 +25,7 @@ jobs: uses: actions/checkout@v2 # required to mount the Github Workspace to a volume - name: Run clang-format-lint - uses: DoozyX/clang-format-lint-action@v0.11 + uses: DoozyX/clang-format-lint-action@v0.18.1 with: source: '.' exclude: './third_party ./external .git' From 97762d7595688ce655e797e1d4a1bc4a3ddb2ffe Mon Sep 17 00:00:00 2001 From: Alex Bailo Date: Tue, 1 Oct 2024 21:41:28 +0200 Subject: [PATCH 17/17] use legacy pattern of Charuco board --- McCalib/src/McCalib.cpp | 2 ++ apps/create_charuco_boards/src/create_charuco_boards.cpp | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/McCalib/src/McCalib.cpp b/McCalib/src/McCalib.cpp index b339ce89..ecc8e7d3 100644 --- a/McCalib/src/McCalib.cpp +++ b/McCalib/src/McCalib.cpp @@ -123,6 +123,7 @@ Calibration::Calibration(const std::string config_path) { new cv::aruco::CharucoBoard(cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), length_square, length_marker, dict_); + charuco->setLegacyPattern(true); charuco_boards[i] = charuco; } else { @@ -136,6 +137,7 @@ Calibration::Calibration(const std::string config_path) { cv::Size(number_x_square_per_board_[i], number_y_square_per_board_[i]), length_square, length_marker, dict_, cur_ids); + charuco->setLegacyPattern(true); charuco_boards[i] = charuco; } diff --git a/apps/create_charuco_boards/src/create_charuco_boards.cpp b/apps/create_charuco_boards/src/create_charuco_boards.cpp index a62cf24e..60d0ae89 100644 --- a/apps/create_charuco_boards/src/create_charuco_boards.cpp +++ b/apps/create_charuco_boards/src/create_charuco_boards.cpp @@ -67,9 +67,10 @@ int main(int argc, char *argv[]) { for (std::size_t i = 0; i < num_board; i++) { if (i == 0) { // if it is the first board then just use the standard idx - const cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( + cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), length_square, length_marker, dict); + charuco.setLegacyPattern(true); charuco_boards.push_back(charuco); } else { @@ -83,6 +84,7 @@ int main(int argc, char *argv[]) { cv::aruco::CharucoBoard charuco = cv::aruco::CharucoBoard( cv::Size(number_x_square_per_board[i], number_y_square_per_board[i]), length_square, length_marker, dict, cur_ids); + charuco.setLegacyPattern(true); charuco_boards.push_back(charuco); }