1
0
mirror of https://github.com/opencv/opencv_contrib.git synced 2025-10-18 17:24:28 +08:00

Fix aruco board tutorial

This commit is contained in:
Sergei Shutov
2022-12-20 18:26:50 +02:00
parent 5d8d02a8e7
commit 00f6afacd1

View File

@@ -36,6 +36,20 @@ The aruco module allows the use of Boards. The main class is the ```cv::aruco::B
cv::Ptr<cv::aruco::Dictionary> dictionary; cv::Ptr<cv::aruco::Dictionary> dictionary;
std::vector<int> ids; std::vector<int> ids;
}; };
struct BoardImpl;
Ptr<BoardImpl> boardImpl;
struct Board::BoardImpl {
std::vector<std::vector<Point3f> > objPoints;
Dictionary dictionary;
Point3f rightBottomBorder;
std::vector<int> ids;
BoardImpl() {
dictionary = Dictionary(getPredefinedDictionary(PredefinedDictionaryType::DICT_4X4_50));
}
};
@endcode @endcode
A object of type ```Board``` has three parameters: A object of type ```Board``` has three parameters:
@@ -56,21 +70,34 @@ The aruco module provides a specific function, ```estimatePoseBoard()```, to per
@code{.cpp} @code{.cpp}
cv::Mat inputImage; cv::Mat inputImage;
// camera parameters are read from somewhere
// Camera parameters are read from somewhere
cv::Mat cameraMatrix, distCoeffs; cv::Mat cameraMatrix, distCoeffs;
// You can read camera parameters from tutorial_camera_params.yml // You can read camera parameters from tutorial_camera_params.yml
readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_board.cpp readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is implemented in aruco_samples_utility.hpp
// assume we have a function to create the board object
// Assume we have a function to create the board object
cv::Ptr<cv::aruco::Board> board = cv::aruco::Board::create(); cv::Ptr<cv::aruco::Board> board = cv::aruco::Board::create();
... ...
std::vector<int> markerIds; std::vector<int> markerIds;
std::vector<std::vector<cv::Point2f>> markerCorners; std::vector<std::vector<cv::Point2f>> markerCorners;
cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds);
// if at least one marker detected cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
if(markerIds.size() > 0) { cv::aruco::ArucoDetector detector(board.dictionary, detectorParams);
detector.detectMarkers(inputImage, markerCorners, markerIds);
cv::Vec3d rvec, tvec; cv::Vec3d rvec, tvec;
// If at least one marker detected
if(markerIds.size() > 0) {
int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec); int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);
} }
@endcode @endcode
The parameters of estimatePoseBoard are: The parameters of estimatePoseBoard are:
@@ -81,7 +108,7 @@ The parameters of estimatePoseBoard are:
- ```rvec``` and ```tvec```: estimated pose of the Board. If not empty then treated as initial guess. - ```rvec``` and ```tvec```: estimated pose of the Board. If not empty then treated as initial guess.
- The function returns the total number of markers employed for estimating the board pose. Note that not all the - The function returns the total number of markers employed for estimating the board pose. Note that not all the
markers provided in ```markerCorners``` and ```markerIds``` should be used, since only the markers whose ids are markers provided in ```markerCorners``` and ```markerIds``` should be used, since only the markers whose ids are
listed in the ```Board::ids``` structure are considered. listed in the ```Board::BoardImpl::ids``` structure are considered.
The ```drawFrameAxes()``` function can be used to check the obtained pose. For instance: The ```drawFrameAxes()``` function can be used to check the obtained pose. For instance:
@@ -135,8 +162,7 @@ in any unit, having in mind that the estimated pose for this board will be measu
- Finally, the dictionary of the markers is provided. - Finally, the dictionary of the markers is provided.
So, this board will be composed by 5x7=35 markers. The ids of each of the markers are assigned, by default, in ascending So, this board will be composed by 5x7=35 markers. The ids of each of the markers are assigned, by default, in ascending
order starting on 0, so they will be 0, 1, 2, ..., 34. This can be easily customized by accessing to the ids vector order starting on 0, so they will be 0, 1, 2, ..., 34.
through ```board.ids```, like in the ```Board``` parent class.
After creating a Grid Board, we probably want to print it and use it. A function to generate the image After creating a Grid Board, we probably want to print it and use it. A function to generate the image
of a ```GridBoard``` is provided in ```cv::aruco::GridBoard::generateImage()```. For example: of a ```GridBoard``` is provided in ```cv::aruco::GridBoard::generateImage()```. For example:
@@ -144,7 +170,7 @@ of a ```GridBoard``` is provided in ```cv::aruco::GridBoard::generateImage()```.
@code{.cpp} @code{.cpp}
cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary); cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
cv::Mat boardImage; cv::Mat boardImage;
board->draw( cv::Size(600, 500), boardImage, 10, 1 ); board->generateImage( cv::Size(600, 500), boardImage, 10, 1 );
@endcode @endcode
- The first parameter is the size of the output image in pixels. In this case 600x500 pixels. If this is not proportional - The first parameter is the size of the output image in pixels. In this case 600x500 pixels. If this is not proportional
@@ -173,13 +199,17 @@ Finally, a full example of board detection:
cv::Mat cameraMatrix, distCoeffs; cv::Mat cameraMatrix, distCoeffs;
// You can read camera parameters from tutorial_camera_params.yml // You can read camera parameters from tutorial_camera_params.yml
readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_board.cpp readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is implemented in aruco_samples_utility.hpp
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250); cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
// To use tutorial sample, you need read custome dictionaty from tutorial_dict.yml
readDictionary(filename, dictionary); // This function is located in detect_board.cpp // To use tutorial sample, you need read custom dictionaty from tutorial_dict.yml
readDictionary(filename, dictionary); // This function is implemented in opencv/modules/objdetect/src/aruco/aruco_dictionary.cpp
cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary); cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
cv::aruco::ArucoDetector detector(dictionary, detectorParams);
while (inputVideo.grab()) { while (inputVideo.grab()) {
cv::Mat image, imageCopy; cv::Mat image, imageCopy;
inputVideo.retrieve(image); inputVideo.retrieve(image);
@@ -187,16 +217,18 @@ Finally, a full example of board detection:
std::vector<int> ids; std::vector<int> ids;
std::vector<std::vector<cv::Point2f> > corners; std::vector<std::vector<cv::Point2f> > corners;
cv::aruco::detectMarkers(image, dictionary, corners, ids);
// if at least one marker detected // Detect markers
detector.detectMarkers(image, corners, ids);
// If at least one marker detected
if (ids.size() > 0) { if (ids.size() > 0) {
cv::aruco::drawDetectedMarkers(imageCopy, corners, ids); cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);
cv::Vec3d rvec, tvec; cv::Vec3d rvec, tvec;
int valid = estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec); int valid = estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec);
// if at least one board marker detected // If at least one board marker detected
if(valid > 0) if(valid > 0)
cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1); cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1);
} }
@@ -269,13 +301,17 @@ internal bits are not analyzed at all and only the corner distances are evaluate
This is an example of using the ```refineDetectedMarkers()``` function: This is an example of using the ```refineDetectedMarkers()``` function:
@code{.cpp} @code{.cpp}
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary); cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
cv::aruco::ArucoDetector detector(dictionary, detectorParams);
std::vector<int> markerIds; std::vector<int> markerIds;
std::vector<std::vector<cv::Point2f>> markerCorners, rejectedCandidates; std::vector<std::vector<cv::Point2f>> markerCorners, rejectedCandidates;
cv::aruco::detectMarkers(inputImage, dictionary, markerCorners, markerIds, cv::aruco::DetectorParameters(), rejectedCandidates); detector.detectMarkers(inputImage, markerCorners, markerIds, rejectedCandidates);
cv::aruco::refineDetectedMarkersinputImage, board, markerCorners, markerIds, rejectedCandidates); detector.refineDetectedMarkers(inputImage, board, markerCorners, markerIds, rejectedCandidates);
// After calling this function, if any new marker has been detected it will be removed from rejectedCandidates and included // After calling this function, if any new marker has been detected it will be removed from rejectedCandidates and included
// at the end of markerCorners and markerIds // at the end of markerCorners and markerIds
@endcode @endcode