@@ -27,61 +27,57 @@ Thus, the pose can be calculated even in the presence of occlusions or partial v
27
27
- The obtained pose is usually more accurate since a higher amount of point correspondences (marker
28
28
corners) are employed.
29
29
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
-
49
30
Board Detection
50
31
-----
51
32
52
33
A Board detection is similar to the standard marker detection. The only difference is in the pose estimation step.
53
34
In fact, to use marker boards, a standard marker detection should be done before estimating the Board pose.
54
35
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 :
56
37
57
38
@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
+
74
72
@endcode
75
73
76
- The parameters of estimatePoseBoard are:
74
+ The parameters are:
77
75
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) .
79
77
- ``` board ``` : the ``` Board ``` object that defines the board layout and its ids
80
78
- ``` cameraMatrix ``` and ``` distCoeffs ``` : camera calibration parameters necessary for pose estimation.
81
79
- ``` 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.
85
81
86
82
The ``` drawFrameAxes() ``` function can be used to check the obtained pose. For instance:
87
83
@@ -135,16 +131,15 @@ in any unit, having in mind that the estimated pose for this board will be measu
135
131
- Finally, the dictionary of the markers is provided.
136
132
137
133
So, 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.
140
135
141
136
After creating a Grid Board, we probably want to print it and use it. A function to generate the image
142
137
of a ``` GridBoard ``` is provided in ``` cv::aruco::GridBoard::generateImage() ``` . For example:
143
138
144
139
@code {.cpp}
145
140
cv::Ptr< cv::aruco::GridBoard > board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
146
141
cv::Mat boardImage;
147
- board->draw ( cv::Size(600, 500), boardImage, 10, 1 );
142
+ board->generateImage ( cv::Size(600, 500), boardImage, 10, 1 );
148
143
@endcode
149
144
150
145
- 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:
173
168
174
169
cv::Mat cameraMatrix, distCoeffs;
175
170
// 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
177
172
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
181
177
cv::Ptr<cv::aruco::GridBoard> board = cv::aruco::GridBoard::create(5, 7, 0.04, 0.01, dictionary);
182
178
179
+ cv::aruco::DetectorParameters detectorParams = cv::aruco::DetectorParameters();
180
+ cv::aruco::ArucoDetector detector(dictionary, detectorParams);
181
+
183
182
while (inputVideo.grab()) {
184
183
cv::Mat image, imageCopy;
185
184
inputVideo.retrieve(image);
186
185
image.copyTo(imageCopy);
187
186
188
187
std::vector<int> ids;
189
188
std::vector<std::vector<cv::Point2f> > corners;
190
- cv::aruco::detectMarkers(image, dictionary, corners, ids);
191
189
192
- // if at least one marker detected
190
+ // Detect markers
191
+ detector.detectMarkers(image, corners, ids);
192
+
193
+ // If at least one marker detected
193
194
if (ids.size() > 0) {
194
195
cv::aruco::drawDetectedMarkers(imageCopy, corners, ids);
195
196
196
197
cv::Vec3d rvec, tvec;
197
- int valid = estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec);
198
198
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)
201
209
cv::drawFrameAxes(imageCopy, cameraMatrix, distCoeffs, rvec, tvec, 0.1);
202
210
}
203
211
@@ -269,13 +277,17 @@ internal bits are not analyzed at all and only the corner distances are evaluate
269
277
This is an example of using the ``` refineDetectedMarkers() ``` function:
270
278
271
279
@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);
273
282
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
+
274
286
std::vector<int> markerIds;
275
287
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);
277
289
278
- cv::aruco::refineDetectedMarkersinputImage , board, markerCorners, markerIds, rejectedCandidates);
290
+ detector.refineDetectedMarkers(inputImage , board, markerCorners, markerIds, rejectedCandidates);
279
291
// After calling this function, if any new marker has been detected it will be removed from rejectedCandidates and included
280
292
// at the end of markerCorners and markerIds
281
293
@endcode
0 commit comments