@@ -27,61 +27,57 @@ Thus, the pose can be calculated even in the presence of occlusions or partial v
2727- The obtained pose is usually more accurate since a higher amount of point correspondences (marker
2828corners) are employed.
2929
30- The aruco module allows the use of Boards. The main class is the ``` cv::aruco::Board ``` class which defines the Board layout:
31-
32- @code {.cpp}
33- class Board {
34- public:
35- std::vector< std::vector<cv::Point3f > > objPoints;
36- cv::Ptr< cv::aruco::Dictionary > dictionary;
37- std::vector<int > ids;
38- };
39- @endcode
40-
41- A object of type ``` Board ``` has three parameters:
42- - The ``` objPoints ``` structure is the list of corner positions in the 3d Board reference system, i.e. its layout.
43- For each marker, its four corners are stored in the standard order, i.e. in clockwise order and starting
44- with the top left corner.
45- - The ``` dictionary ``` parameter indicates to which marker dictionary the Board markers belong to.
46- - Finally, the ``` ids ``` structure indicates the identifiers of each of the markers in ``` objPoints ``` respect to the specified ``` dictionary ``` .
47-
48-
4930Board Detection
5031-----
5132
5233A Board detection is similar to the standard marker detection. The only difference is in the pose estimation step.
5334In fact, to use marker boards, a standard marker detection should be done before estimating the Board pose.
5435
55- The aruco module provides a specific function, ``` estimatePoseBoard() ``` , to perform pose estimation for boards :
36+ To perform pose estimation for boards, you should use ``` #cv::solvePnP ``` function, as shown below :
5637
5738@code {.cpp}
58- cv::Mat inputImage;
59- // camera parameters are read from somewhere
60- cv::Mat cameraMatrix, distCoeffs;
61- // You can read camera parameters from tutorial_camera_params.yml
62- readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_board.cpp
63- // assume we have a function to create the board object
64- cv::Ptr< cv::aruco::Board > board = cv::aruco::Board::create();
65- ...
66- std::vector<int > markerIds;
67- std::vector< std::vector<cv::Point2f > > markerCorners;
68- cv::aruco::detectMarkers(inputImage, board.dictionary, markerCorners, markerIds);
69- // if at least one marker detected
70- if(markerIds.size() > 0) {
71- cv::Vec3d rvec, tvec;
72- int valid = cv::aruco::estimatePoseBoard(markerCorners, markerIds, board, cameraMatrix, distCoeffs, rvec, tvec);
73- }
39+ cv::Mat inputImage;
40+
41+ // Camera parameters are read from somewhere
42+ cv::Mat cameraMatrix, distCoeffs;
43+
44+ // You can read camera parameters from tutorial_camera_params.yml
45+ readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is implemented in aruco_samples_utility.hpp
46+
47+ // Assume we have a function to create the board object
48+ cv::Ptr< cv::aruco::Board > board = cv::aruco::Board::create();
49+
50+ ...
51+
52+ std::vector<int > markerIds;
53+ std::vector< std::vector<cv::Point2f > > markerCorners;
54+
55+ cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
56+ cv::aruco::ArucoDetector detector(board.dictionary, detectorParams);
57+
58+ detector.detectMarkers(inputImage, markerCorners, markerIds);
59+
60+ cv::Vec3d rvec, tvec;
61+
62+ // If at least one marker detected
63+ if(markerIds.size() > 0) {
64+ // Get object and image points for the solvePnP function
65+ cv::Mat objPoints, imgPoints;
66+ board->matchImagePoints(markerCorners, markerIds, objPoints, imgPoints);
67+
68+ // Find pose
69+ cv::solvePnP(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec);
70+ }
71+
7472@endcode
7573
76- The parameters of estimatePoseBoard are:
74+ The parameters are:
7775
78- - ``` markerCorners ``` and ``` markerIds ``` : structures of detected markers from ``` detectMarkers() ``` function.
76+ - ``` objPoints ``` , ``` imgPoints ``` : object and image points, matched with ``` matchImagePoints ``` , which, in turn, takes as input ``` markerCorners ``` and ``` markerIds ``` : structures of detected markers from ``` detectMarkers() ``` function) .
7977- ``` board ``` : the ``` Board ``` object that defines the board layout and its ids
8078- ``` cameraMatrix ``` and ``` distCoeffs ``` : camera calibration parameters necessary for pose estimation.
8179- ``` rvec ``` and ``` tvec ``` : estimated pose of the Board. If not empty then treated as initial guess.
82- - The function returns the total number of markers employed for estimating the board pose. Note that not all the
83- markers provided in ``` markerCorners ``` and ``` markerIds ``` should be used, since only the markers whose ids are
84- listed in the ``` Board::ids ``` structure are considered.
80+ - The function returns the total number of markers employed for estimating the board pose.
8581
8682The ``` drawFrameAxes() ``` function can be used to check the obtained pose. For instance:
8783
@@ -135,16 +131,15 @@ in any unit, having in mind that the estimated pose for this board will be measu
135131- Finally, the dictionary of the markers is provided.
136132
137133So, this board will be composed by 5x7=35 markers. The ids of each of the markers are assigned, by default, in ascending
138- order starting on 0, so they will be 0, 1, 2, ..., 34. This can be easily customized by accessing to the ids vector
139- through ``` board.ids ``` , like in the ``` Board ``` parent class.
134+ order starting on 0, so they will be 0, 1, 2, ..., 34.
140135
141136After creating a Grid Board, we probably want to print it and use it. A function to generate the image
142137of a ``` GridBoard ``` is provided in ``` cv::aruco::GridBoard::generateImage() ``` . For example:
143138
144139@code {.cpp}
145140 cv::Ptr< cv::aruco::GridBoard > board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
146141 cv::Mat boardImage;
147- board->draw ( cv::Size(600, 500), boardImage, 10, 1 );
142+ board->generateImage ( cv::Size(600, 500), boardImage, 10, 1 );
148143@endcode
149144
150145- The first parameter is the size of the output image in pixels. In this case 600x500 pixels. If this is not proportional
@@ -173,31 +168,44 @@ Finally, a full example of board detection:
173168
174169 cv::Mat cameraMatrix, distCoeffs;
175170 // You can read camera parameters from tutorial_camera_params.yml
176- readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is located in detect_board.cpp
171+ readCameraParameters(filename, cameraMatrix, distCoeffs); // This function is implemented in aruco_samples_utility.hpp
177172
178- cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
179- // To use tutorial sample, you need read custome dictionaty from tutorial_dict.yml
180- readDictionary(filename, dictionary); // This function is located in detect_board.cpp
173+ cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
174+
175+ // To use tutorial sample, you need read custom dictionaty from tutorial_dict.yml
176+ readDictionary(filename, dictionary); // This function is implemented in opencv/modules/objdetect/src/aruco/aruco_dictionary.cpp
181177 cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
182178
179+ cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
180+ cv::aruco::ArucoDetector detector(dictionary, detectorParams);
181+
183182 while (inputVideo.grab()) {
184183 cv::Mat image, imageCopy;
185184 inputVideo.retrieve(image);
186185 image.copyTo(imageCopy);
187186
188187 std::vector<int> ids;
189188 std::vector<std::vector<cv::Point2f> > corners;
190- cv::aruco::detectMarkers(image, dictionary, corners, ids);
191189
192- // if at least one marker detected
190+ // Detect markers
191+ detector.detectMarkers(image, corners, ids);
192+
193+ // If at least one marker detected
193194 if (ids.size() > 0) {
194195 cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);
195196
196197 cv::Vec3d rvec, tvec;
197- int valid = estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec);
198198
199- // if at least one board marker detected
200- if(valid > 0)
199+ // Get object and image points for the solvePnP function
200+ cv::Mat objPoints, imgPoints;
201+ board->matchImagePoints(corners, ids, objPoints, imgPoints);
202+
203+ // Find pose
204+ cv::solvePnP(objPoints, imgPoints, cameraMatrix, distCoeffs, rvec, tvec);
205+
206+ // If at least one board marker detected
207+ markersOfBoardDetected = (int)objPoints.total() / 4;
208+ if(markersOfBoardDetected > 0)
201209 cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1);
202210 }
203211
@@ -269,13 +277,17 @@ internal bits are not analyzed at all and only the corner distances are evaluate
269277This is an example of using the ``` refineDetectedMarkers() ``` function:
270278
271279@code {.cpp}
272- cv::Ptr< cv::aruco::Dictionary > dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
280+
281+ cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);
273282 cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
283+ cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
284+ cv::aruco::ArucoDetector detector(dictionary, detectorParams);
285+
274286 std::vector<int> markerIds;
275287 std::vector<std::vector<cv::Point2f>> markerCorners, rejectedCandidates;
276- cv::aruco:: detectMarkers(inputImage, dictionary, markerCorners, markerIds, cv::aruco::DetectorParameters() , rejectedCandidates);
288+ detector. detectMarkers(inputImage, markerCorners, markerIds, rejectedCandidates);
277289
278- cv::aruco::refineDetectedMarkersinputImage , board, markerCorners, markerIds, rejectedCandidates);
290+ detector.refineDetectedMarkers(inputImage , board, markerCorners, markerIds, rejectedCandidates);
279291 // After calling this function, if any new marker has been detected it will be removed from rejectedCandidates and included
280292 // at the end of markerCorners and markerIds
281293@endcode
0 commit comments