@@ -200,6 +200,15 @@ float GridBoard::getMarkerSeparation() {
200
200
return gridImpl->markerSeparation ;
201
201
}
202
202
203
+ struct CharucoBoard ::CharucoImpl : GridBoard::GridImpl {
204
+ // size of chessboard squares side (normally in meters)
205
+ float squareLength;
206
+
207
+ // marker side length (normally in meters)
208
+ float markerLength;
209
+ };
210
+
211
+ CharucoBoard::CharucoBoard (): charucoImpl(makePtr<CharucoImpl>()) {}
203
212
204
213
void CharucoBoard::draw (Size outSize, OutputArray _img, int marginSize, int borderBits) {
205
214
CV_Assert (!outSize.empty ());
@@ -212,8 +221,8 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
212
221
out.colRange (marginSize, out.cols - marginSize).rowRange (marginSize, out.rows - marginSize);
213
222
214
223
double totalLengthX, totalLengthY;
215
- totalLengthX = _squareLength * _squaresX ;
216
- totalLengthY = _squareLength * _squaresY ;
224
+ totalLengthX = charucoImpl-> squareLength * charucoImpl-> sizeX ;
225
+ totalLengthY = charucoImpl-> squareLength * charucoImpl-> sizeY ;
217
226
218
227
// proportional transformation
219
228
double xReduction = totalLengthX / double (noMarginsImg.cols );
@@ -233,21 +242,21 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
233
242
234
243
// determine the margins to draw only the markers
235
244
// take the minimum just to be sure
236
- double squareSizePixels = min (double (chessboardZoneImg.cols ) / double (_squaresX ),
237
- double (chessboardZoneImg.rows ) / double (_squaresY ));
245
+ double squareSizePixels = min (double (chessboardZoneImg.cols ) / double (charucoImpl-> sizeX ),
246
+ double (chessboardZoneImg.rows ) / double (charucoImpl-> sizeY ));
238
247
239
- double diffSquareMarkerLength = (_squareLength - _markerLength ) / 2 ;
248
+ double diffSquareMarkerLength = (charucoImpl-> squareLength - charucoImpl-> markerLength ) / 2 ;
240
249
int diffSquareMarkerLengthPixels =
241
- int (diffSquareMarkerLength * squareSizePixels / _squareLength );
250
+ int (diffSquareMarkerLength * squareSizePixels / charucoImpl-> squareLength );
242
251
243
252
// draw markers
244
253
Mat markersImg;
245
254
_drawPlanarBoardImpl (this , chessboardZoneImg.size (), markersImg, diffSquareMarkerLengthPixels, borderBits);
246
255
markersImg.copyTo (chessboardZoneImg);
247
256
248
257
// now draw black squares
249
- for (int y = 0 ; y < _squaresY ; y++) {
250
- for (int x = 0 ; x < _squaresX ; x++) {
258
+ for (int y = 0 ; y < charucoImpl-> sizeY ; y++) {
259
+ for (int x = 0 ; x < charucoImpl-> sizeX ; x++) {
251
260
252
261
if (y % 2 != x % 2 ) continue ; // white corner, dont do anything
253
262
@@ -263,15 +272,67 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
263
272
}
264
273
}
265
274
275
+ /* *
276
+ * Fill nearestMarkerIdx and nearestMarkerCorners arrays
277
+ */
278
+ static inline void _getNearestMarkerCorners (CharucoBoard &board, float squareLength) {
279
+ board.nearestMarkerIdx .resize (board.chessboardCorners .size ());
280
+ board.nearestMarkerCorners .resize (board.chessboardCorners .size ());
281
+
282
+ unsigned int nMarkers = (unsigned int )board.ids .size ();
283
+ unsigned int nCharucoCorners = (unsigned int )board.chessboardCorners .size ();
284
+ for (unsigned int i = 0 ; i < nCharucoCorners; i++) {
285
+ double minDist = -1 ; // distance of closest markers
286
+ Point3f charucoCorner = board.chessboardCorners [i];
287
+ for (unsigned int j = 0 ; j < nMarkers; j++) {
288
+ // calculate distance from marker center to charuco corner
289
+ Point3f center = Point3f (0 , 0 , 0 );
290
+ for (unsigned int k = 0 ; k < 4 ; k++)
291
+ center += board.objPoints [j][k];
292
+ center /= 4 .;
293
+ double sqDistance;
294
+ Point3f distVector = charucoCorner - center;
295
+ sqDistance = distVector.x * distVector.x + distVector.y * distVector.y ;
296
+ if (j == 0 || fabs (sqDistance - minDist) < cv::pow (0.01 * squareLength, 2 )) {
297
+ // if same minimum distance (or first iteration), add to nearestMarkerIdx vector
298
+ board.nearestMarkerIdx [i].push_back (j);
299
+ minDist = sqDistance;
300
+ } else if (sqDistance < minDist) {
301
+ // if finding a closest marker to the charuco corner
302
+ board.nearestMarkerIdx [i].clear (); // remove any previous added marker
303
+ board.nearestMarkerIdx [i].push_back (j); // add the new closest marker index
304
+ minDist = sqDistance;
305
+ }
306
+ }
307
+ // for each of the closest markers, search the marker corner index closer
308
+ // to the charuco corner
309
+ for (unsigned int j = 0 ; j < board.nearestMarkerIdx [i].size (); j++) {
310
+ board.nearestMarkerCorners [i].resize (board.nearestMarkerIdx [i].size ());
311
+ double minDistCorner = -1 ;
312
+ for (unsigned int k = 0 ; k < 4 ; k++) {
313
+ double sqDistance;
314
+ Point3f distVector = charucoCorner - board.objPoints [board.nearestMarkerIdx [i][j]][k];
315
+ sqDistance = distVector.x * distVector.x + distVector.y * distVector.y ;
316
+ if (k == 0 || sqDistance < minDistCorner) {
317
+ // if this corner is closer to the charuco corner, assing its index
318
+ // to nearestMarkerCorners
319
+ minDistCorner = sqDistance;
320
+ board.nearestMarkerCorners [i][j] = k;
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+
266
327
Ptr<CharucoBoard> CharucoBoard::create (int squaresX, int squaresY, float squareLength,
267
328
float markerLength, const Ptr<Dictionary> &dictionary) {
268
329
CV_Assert (squaresX > 1 && squaresY > 1 && markerLength > 0 && squareLength > markerLength);
269
330
Ptr<CharucoBoard> res = makePtr<CharucoBoard>();
270
331
271
- res->_squaresX = squaresX;
272
- res->_squaresY = squaresY;
273
- res->_squareLength = squareLength;
274
- res->_markerLength = markerLength;
332
+ res->charucoImpl -> sizeX = squaresX;
333
+ res->charucoImpl -> sizeY = squaresY;
334
+ res->charucoImpl -> squareLength = squareLength;
335
+ res->charucoImpl -> markerLength = markerLength;
275
336
res->dictionary = dictionary;
276
337
277
338
float diffSquareMarkerLength = (squareLength - markerLength) / 2 ;
@@ -306,62 +367,15 @@ Ptr<CharucoBoard> CharucoBoard::create(int squaresX, int squaresY, float squareL
306
367
}
307
368
res->rightBottomBorder = Point3f (squaresX * squareLength,
308
369
squaresY * squareLength, 0 .f );
309
- res->_getNearestMarkerCorners ();
310
-
370
+ _getNearestMarkerCorners (*res, res->charucoImpl ->squareLength );
311
371
return res;
312
372
}
313
373
314
- /* *
315
- * Fill nearestMarkerIdx and nearestMarkerCorners arrays
316
- */
317
- void CharucoBoard::_getNearestMarkerCorners () {
318
- nearestMarkerIdx.resize (chessboardCorners.size ());
319
- nearestMarkerCorners.resize (chessboardCorners.size ());
374
+ Size CharucoBoard::getChessboardSize () const { return Size (charucoImpl->sizeX , charucoImpl->sizeY ); }
320
375
321
- unsigned int nMarkers = (unsigned int )ids.size ();
322
- unsigned int nCharucoCorners = (unsigned int )chessboardCorners.size ();
323
- for (unsigned int i = 0 ; i < nCharucoCorners; i++) {
324
- double minDist = -1 ; // distance of closest markers
325
- Point3f charucoCorner = chessboardCorners[i];
326
- for (unsigned int j = 0 ; j < nMarkers; j++) {
327
- // calculate distance from marker center to charuco corner
328
- Point3f center = Point3f (0 , 0 , 0 );
329
- for (unsigned int k = 0 ; k < 4 ; k++)
330
- center += objPoints[j][k];
331
- center /= 4 .;
332
- double sqDistance;
333
- Point3f distVector = charucoCorner - center;
334
- sqDistance = distVector.x * distVector.x + distVector.y * distVector.y ;
335
- if (j == 0 || fabs (sqDistance - minDist) < cv::pow (0.01 * _squareLength, 2 )) {
336
- // if same minimum distance (or first iteration), add to nearestMarkerIdx vector
337
- nearestMarkerIdx[i].push_back (j);
338
- minDist = sqDistance;
339
- } else if (sqDistance < minDist) {
340
- // if finding a closest marker to the charuco corner
341
- nearestMarkerIdx[i].clear (); // remove any previous added marker
342
- nearestMarkerIdx[i].push_back (j); // add the new closest marker index
343
- minDist = sqDistance;
344
- }
345
- }
346
- // for each of the closest markers, search the marker corner index closer
347
- // to the charuco corner
348
- for (unsigned int j = 0 ; j < nearestMarkerIdx[i].size (); j++) {
349
- nearestMarkerCorners[i].resize (nearestMarkerIdx[i].size ());
350
- double minDistCorner = -1 ;
351
- for (unsigned int k = 0 ; k < 4 ; k++) {
352
- double sqDistance;
353
- Point3f distVector = charucoCorner - objPoints[nearestMarkerIdx[i][j]][k];
354
- sqDistance = distVector.x * distVector.x + distVector.y * distVector.y ;
355
- if (k == 0 || sqDistance < minDistCorner) {
356
- // if this corner is closer to the charuco corner, assing its index
357
- // to nearestMarkerCorners
358
- minDistCorner = sqDistance;
359
- nearestMarkerCorners[i][j] = k;
360
- }
361
- }
362
- }
363
- }
364
- }
376
+ float CharucoBoard::getSquareLength () const { return charucoImpl->squareLength ; }
377
+
378
+ float CharucoBoard::getMarkerLength () const { return charucoImpl->markerLength ; }
365
379
366
380
bool testCharucoCornersCollinear (const Ptr<CharucoBoard> &_board, InputArray _charucoIds) {
367
381
unsigned int nCharucoCorners = (unsigned int )_charucoIds.getMat ().total ();
0 commit comments