@@ -46,15 +46,19 @@ namespace opencv_test { namespace {
46
46
* @brief Get a synthetic image of Chessboard in perspective
47
47
*/
48
48
static Mat projectChessboard (int squaresX, int squaresY, float squareSize, Size imageSize,
49
- Mat cameraMatrix, Mat rvec, Mat tvec) {
49
+ Mat cameraMatrix, Mat rvec, Mat tvec, bool legacy ) {
50
50
51
51
Mat img (imageSize, CV_8UC1, Scalar::all (255 ));
52
52
Mat distCoeffs (5 , 1 , CV_64FC1, Scalar::all (0 ));
53
53
54
54
for (int y = 0 ; y < squaresY; y++) {
55
55
float startY = float (y) * squareSize;
56
56
for (int x = 0 ; x < squaresX; x++) {
57
- if (y % 2 != x % 2 ) continue ;
57
+ if (legacy) {
58
+ if ((y + ((squaresY + 1 ) % 2 )) % 2 != x % 2 ) continue ;
59
+ } else {
60
+ if (y % 2 != x % 2 ) continue ;
61
+ }
58
62
float startX = float (x) * squareSize;
59
63
60
64
vector< Point3f > squareCorners;
@@ -101,7 +105,7 @@ static Mat projectCharucoBoard(Ptr<aruco::CharucoBoard> &board, Mat cameraMatrix
101
105
// project chessboard
102
106
Mat chessboard =
103
107
projectChessboard (board->getChessboardSize ().width , board->getChessboardSize ().height ,
104
- board->getSquareLength (), imageSize, cameraMatrix, rvec, tvec);
108
+ board->getSquareLength (), imageSize, cameraMatrix, rvec, tvec, board-> getLegacyFlag () );
105
109
106
110
for (unsigned int i = 0 ; i < chessboard.total (); i++) {
107
111
if (chessboard.ptr < unsigned char >()[i] == 0 ) {
@@ -130,84 +134,85 @@ CV_CharucoDetection::CV_CharucoDetection() {}
130
134
void CV_CharucoDetection::run (int ) {
131
135
132
136
int iter = 0 ;
133
- Mat cameraMatrix = Mat::eye (3 , 3 , CV_64FC1);
134
137
Size imgSize (500 , 500 );
135
- Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary (aruco::DICT_6X6_250);
136
- Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create (4 , 4 , 0 .03f , 0 .015f , dictionary);
137
-
138
+ Mat cameraMatrix = Mat::eye (3 , 3 , CV_64FC1);
138
139
cameraMatrix.at < double >(0 , 0 ) = cameraMatrix.at < double >(1 , 1 ) = 600 ;
139
140
cameraMatrix.at < double >(0 , 2 ) = imgSize.width / 2 ;
140
141
cameraMatrix.at < double >(1 , 2 ) = imgSize.height / 2 ;
141
-
142
142
Mat distCoeffs (5 , 1 , CV_64FC1, Scalar::all (0 ));
143
143
144
- // for different perspectives
145
- for (double distance = 0.2 ; distance <= 0.4 ; distance += 0.2 ) {
146
- for (int yaw = -55 ; yaw <= 50 ; yaw += 25 ) {
147
- for (int pitch = -55 ; pitch <= 50 ; pitch += 25 ) {
148
-
149
- int markerBorder = iter % 2 + 1 ;
150
- iter++;
151
-
152
- // create synthetic image
153
- Mat rvec, tvec;
154
- Mat img = projectCharucoBoard (board, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
155
- distance, imgSize, markerBorder, rvec, tvec);
156
-
157
- // detect markers
158
- vector< vector< Point2f > > corners;
159
- vector< int > ids;
160
- Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create ();
161
- params->minDistanceToBorder = 3 ;
162
- params->markerBorderBits = markerBorder;
163
- aruco::detectMarkers (img, dictionary, corners, ids, params);
164
-
165
- if (ids.size () == 0 ) {
166
- ts->printf (cvtest::TS::LOG, " Marker detection failed" );
167
- ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
168
- return ;
169
- }
144
+ Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary (aruco::DICT_6X6_250);
145
+ for (bool legacy : {true , false }) {
146
+ Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create (4 , 4 , 0 .04f , 0 .03f , dictionary, legacy);
147
+
148
+ // for different perspectives
149
+ for (double distance = 0.2 ; distance <= 0.4 ; distance += 0.2 ) {
150
+ for (int yaw = -55 ; yaw <= 50 ; yaw += 25 ) {
151
+ for (int pitch = -55 ; pitch <= 50 ; pitch += 25 ) {
152
+
153
+ int markerBorder = iter % 2 + 1 ;
154
+ iter++;
155
+
156
+ // create synthetic image
157
+ Mat rvec, tvec;
158
+ Mat img = projectCharucoBoard (board, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
159
+ distance, imgSize, markerBorder, rvec, tvec);
160
+
161
+ // detect markers
162
+ vector< vector< Point2f > > corners;
163
+ vector< int > ids;
164
+ Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create ();
165
+ params->minDistanceToBorder = 3 ;
166
+ params->markerBorderBits = markerBorder;
167
+ aruco::detectMarkers (img, dictionary, corners, ids, params);
168
+
169
+ if (ids.size () == 0 ) {
170
+ ts->printf (cvtest::TS::LOG, " Marker detection failed" );
171
+ ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
172
+ return ;
173
+ }
170
174
171
- // interpolate charuco corners
172
- vector< Point2f > charucoCorners;
173
- vector< int > charucoIds;
175
+ // interpolate charuco corners
176
+ vector< Point2f > charucoCorners;
177
+ vector< int > charucoIds;
174
178
175
- if (iter % 2 == 0 ) {
176
- aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
177
- charucoIds);
178
- } else {
179
- aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
180
- charucoIds, cameraMatrix, distCoeffs);
181
- }
179
+ if (iter % 2 == 0 ) {
180
+ aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
181
+ charucoIds);
182
+ } else {
183
+ aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
184
+ charucoIds, cameraMatrix, distCoeffs);
185
+ }
182
186
183
- // check results
184
- vector< Point2f > projectedCharucoCorners;
187
+ // check results
188
+ vector< Point2f > projectedCharucoCorners;
185
189
186
- // copy chessboardCorners
187
- vector<Point3f> copyChessboardCorners = board->chessboardCorners ;
188
- // move copyChessboardCorners points
189
- for (size_t i = 0 ; i < copyChessboardCorners.size (); i++)
190
- copyChessboardCorners[i] -= board->rightBottomBorder / 2 .f ;
191
- projectPoints (copyChessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
192
- projectedCharucoCorners);
190
+ // copy chessboardCorners
191
+ vector<Point3f> copyChessboardCorners = board->chessboardCorners ;
192
+ // move copyChessboardCorners points
193
+ for (size_t i = 0 ; i < copyChessboardCorners.size (); i++)
194
+ copyChessboardCorners[i] -= board->rightBottomBorder / 2 .f ;
195
+ projectPoints (copyChessboardCorners, rvec, tvec, cameraMatrix, distCoeffs,
196
+ projectedCharucoCorners);
193
197
194
- for (unsigned int i = 0 ; i < charucoIds.size (); i++) {
198
+ for (unsigned int i = 0 ; i < charucoIds.size (); i++) {
195
199
196
- int currentId = charucoIds[i];
200
+ int currentId = charucoIds[i];
197
201
198
- if (currentId >= (int )board->chessboardCorners .size ()) {
199
- ts->printf (cvtest::TS::LOG, " Invalid Charuco corner id" );
200
- ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
201
- return ;
202
- }
202
+ if (currentId >= (int )board->chessboardCorners .size ()) {
203
+ ts->printf (cvtest::TS::LOG, " Invalid Charuco corner id" );
204
+ ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
205
+ return ;
206
+ }
203
207
204
- double repError = cv::norm (charucoCorners[i] - projectedCharucoCorners[currentId]); // TODO cvtest
208
+ double repError = cv::norm (charucoCorners[i] - projectedCharucoCorners[currentId]); // TODO cvtest
205
209
206
210
207
- if (repError > 5 .) {
208
- ts->printf (cvtest::TS::LOG, " Charuco corner reprojection error too high" );
209
- ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
210
- return ;
211
+ if (repError > 5 .) {
212
+ ts->printf (cvtest::TS::LOG, " Charuco corner reprojection error too high" );
213
+ ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
214
+ return ;
215
+ }
211
216
}
212
217
}
213
218
}
@@ -235,91 +240,101 @@ CV_CharucoPoseEstimation::CV_CharucoPoseEstimation() {}
235
240
void CV_CharucoPoseEstimation::run (int ) {
236
241
237
242
int iter = 0 ;
243
+ Size imgSize (750 , 750 );
238
244
Mat cameraMatrix = Mat::eye (3 , 3 , CV_64FC1);
239
- Size imgSize (500 , 500 );
240
- Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary (aruco::DICT_6X6_250);
241
- Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create (4 , 4 , 0 .03f , 0 .015f , dictionary);
242
-
243
245
cameraMatrix.at < double >(0 , 0 ) = cameraMatrix.at < double >(1 , 1 ) = 650 ;
244
246
cameraMatrix.at < double >(0 , 2 ) = imgSize.width / 2 ;
245
247
cameraMatrix.at < double >(1 , 2 ) = imgSize.height / 2 ;
246
-
247
248
Mat distCoeffs (5 , 1 , CV_64FC1, Scalar::all (0 ));
248
- // for different perspectives
249
- for (double distance = 0.2 ; distance <= 0.3 ; distance += 0.1 ) {
250
- for (int yaw = -55 ; yaw <= 50 ; yaw += 25 ) {
251
- for (int pitch = -55 ; pitch <= 50 ; pitch += 25 ) {
252
-
253
- int markerBorder = iter % 2 + 1 ;
254
- iter++;
255
-
256
- // get synthetic image
257
- Mat rvec, tvec;
258
- Mat img = projectCharucoBoard (board, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
259
- distance, imgSize, markerBorder, rvec, tvec);
260
-
261
- // detect markers
262
- vector< vector< Point2f > > corners;
263
- vector< int > ids;
264
- Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create ();
265
- params->minDistanceToBorder = 3 ;
266
- params->markerBorderBits = markerBorder;
267
- aruco::detectMarkers (img, dictionary, corners, ids, params);
268
-
269
- ASSERT_EQ (ids.size (), board->ids .size ());
270
-
271
- // interpolate charuco corners
272
- vector< Point2f > charucoCorners;
273
- vector< int > charucoIds;
274
-
275
- if (iter % 2 == 0 ) {
276
- aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
277
- charucoIds);
278
- } else {
279
- aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
280
- charucoIds, cameraMatrix, distCoeffs);
281
- }
282
-
283
- if (charucoIds.size () == 0 ) continue ;
284
-
285
- // estimate charuco pose
286
- aruco::estimatePoseCharucoBoard (charucoCorners, charucoIds, board, cameraMatrix,
287
- distCoeffs, rvec, tvec);
288
249
250
+ Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary (aruco::DICT_6X6_250);
251
+ for (bool legacy : {true , false }) {
252
+ Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create (4 , 4 , 0 .04f , 0 .03f , dictionary, legacy);
253
+
254
+ // for different perspectives
255
+ for (double distance = 0.2 ; distance <= 0.3 ; distance += 0.1 ) {
256
+ for (int yaw = -55 ; yaw <= 50 ; yaw += 25 ) {
257
+ for (int pitch = -55 ; pitch <= 50 ; pitch += 25 ) {
258
+
259
+ int markerBorder = iter % 2 + 1 ;
260
+ iter++;
261
+
262
+ // get synthetic image
263
+ Mat rvec, tvec;
264
+ Mat img = projectCharucoBoard (board, cameraMatrix, deg2rad (yaw), deg2rad (pitch),
265
+ distance, imgSize, markerBorder, rvec, tvec);
266
+
267
+ // detect markers
268
+ vector< vector< Point2f > > corners;
269
+ vector< int > ids;
270
+ Ptr<aruco::DetectorParameters> params = aruco::DetectorParameters::create ();
271
+ params->minDistanceToBorder = 3 ;
272
+ params->markerBorderBits = markerBorder;
273
+ aruco::detectMarkers (img, dictionary, corners, ids, params);
274
+
275
+ ASSERT_EQ (ids.size (), board->ids .size ());
276
+
277
+ // interpolate charuco corners
278
+ vector< Point2f > charucoCorners;
279
+ vector< int > charucoIds;
280
+
281
+ if (iter % 2 == 0 ) {
282
+ aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
283
+ charucoIds);
284
+ } else {
285
+ aruco::interpolateCornersCharuco (corners, ids, img, board, charucoCorners,
286
+ charucoIds, cameraMatrix, distCoeffs);
287
+ }
289
288
290
- // check axes
291
- const float offset = (board->getSquareLength () - board->getMarkerLength ()) / 2 .f ;
292
- vector<Point2f> axes = getAxis (cameraMatrix, distCoeffs, rvec, tvec, board->getSquareLength (), offset);
293
- vector<Point2f> topLeft = getMarkerById (board->ids [0 ], corners, ids);
294
- ASSERT_NEAR (topLeft[0 ].x , axes[1 ].x , 3 .f );
295
- ASSERT_NEAR (topLeft[0 ].y , axes[1 ].y , 3 .f );
296
- vector<Point2f> bottomLeft = getMarkerById (board->ids [2 ], corners, ids);
297
- ASSERT_NEAR (bottomLeft[0 ].x , axes[2 ].x , 3 .f );
298
- ASSERT_NEAR (bottomLeft[0 ].y , axes[2 ].y , 3 .f );
289
+ if (charucoIds.size () == 0 ) continue ;
290
+
291
+ // estimate charuco pose
292
+ aruco::estimatePoseCharucoBoard (charucoCorners, charucoIds, board, cameraMatrix,
293
+ distCoeffs, rvec, tvec);
294
+
295
+ // check axes
296
+ const float aruco_offset = (board->getSquareLength () - board->getMarkerLength ()) / 2 .f ;
297
+ Point2f offset;
298
+ vector<Point2f> topLeft, bottomLeft;
299
+ if (legacy && (board->getChessboardSize ().height % 2 == 0 )) { // legacy and even row count
300
+ offset = Point2f (aruco_offset + board->getSquareLength (), aruco_offset);
301
+ topLeft = getMarkerById (board->ids [1 ], corners, ids);
302
+ bottomLeft = getMarkerById (board->ids [2 ], corners, ids);
303
+ } else {
304
+ offset = Point2f (aruco_offset, aruco_offset);
305
+ topLeft = getMarkerById (board->ids [0 ], corners, ids);
306
+ bottomLeft = getMarkerById (board->ids [2 ], corners, ids);
307
+ }
308
+ vector<Point2f> axes = getAxis (cameraMatrix, distCoeffs, rvec, tvec, board->getSquareLength (), offset);
309
+ ASSERT_NEAR (topLeft[0 ].x , axes[1 ].x , 3 .f );
310
+ ASSERT_NEAR (topLeft[0 ].y , axes[1 ].y , 3 .f );
311
+ ASSERT_NEAR (bottomLeft[0 ].x , axes[2 ].x , 3 .f );
312
+ ASSERT_NEAR (bottomLeft[0 ].y , axes[2 ].y , 3 .f );
299
313
300
- // check estimate result
301
- vector< Point2f > projectedCharucoCorners;
314
+ // check estimate result
315
+ vector< Point2f > projectedCharucoCorners;
302
316
303
- projectPoints (board->chessboardCorners , rvec, tvec, cameraMatrix, distCoeffs,
304
- projectedCharucoCorners);
317
+ projectPoints (board->chessboardCorners , rvec, tvec, cameraMatrix, distCoeffs,
318
+ projectedCharucoCorners);
305
319
306
- for (unsigned int i = 0 ; i < charucoIds.size (); i++) {
320
+ for (unsigned int i = 0 ; i < charucoIds.size (); i++) {
307
321
308
- int currentId = charucoIds[i];
322
+ int currentId = charucoIds[i];
309
323
310
- if (currentId >= (int )board->chessboardCorners .size ()) {
311
- ts->printf (cvtest::TS::LOG, " Invalid Charuco corner id" );
312
- ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
313
- return ;
314
- }
324
+ if (currentId >= (int )board->chessboardCorners .size ()) {
325
+ ts->printf (cvtest::TS::LOG, " Invalid Charuco corner id" );
326
+ ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
327
+ return ;
328
+ }
315
329
316
- double repError = cv::norm (charucoCorners[i] - projectedCharucoCorners[currentId]); // TODO cvtest
330
+ double repError = cv::norm (charucoCorners[i] - projectedCharucoCorners[currentId]); // TODO cvtest
317
331
318
332
319
- if (repError > 5 .) {
320
- ts->printf (cvtest::TS::LOG, " Charuco corner reprojection error too high" );
321
- ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
322
- return ;
333
+ if (repError > 5 .) {
334
+ ts->printf (cvtest::TS::LOG, " Charuco corner reprojection error too high" );
335
+ ts->set_failed_test_info (cvtest::TS::FAIL_MISMATCH);
336
+ return ;
337
+ }
323
338
}
324
339
}
325
340
}
0 commit comments