Skip to content

Commit ba4d60e

Browse files
author
AleksandrPanov
committed
add charucoImpl
1 parent b511cfa commit ba4d60e

File tree

2 files changed

+88
-80
lines changed

2 files changed

+88
-80
lines changed

modules/aruco/include/opencv2/aruco/board.hpp

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class CV_EXPORTS_W GridBoard : public Board {
129129
protected:
130130
struct GridImpl;
131131
Ptr<GridImpl> gridImpl;
132+
friend class CharucoBoard;
132133
};
133134

134135
/**
@@ -141,15 +142,16 @@ class CV_EXPORTS_W GridBoard : public Board {
141142
*/
142143
class CV_EXPORTS_W CharucoBoard : public Board {
143144
public:
145+
CharucoBoard();
146+
144147
// vector of chessboard 3D corners precalculated
145148
CV_PROP std::vector<Point3f> chessboardCorners;
146149

147150
// for each charuco corner, nearest marker id and nearest marker corner id of each marker
148151
CV_PROP std::vector<std::vector<int> > nearestMarkerIdx;
149152
CV_PROP std::vector<std::vector<int> > nearestMarkerCorners;
150153

151-
/**
152-
* @brief Draw a ChArUco board
154+
/** @brief Draw a ChArUco board
153155
*
154156
* @param outSize size of the output image in pixels.
155157
* @param img output image with the board. The size of this image will be outSize
@@ -177,21 +179,13 @@ class CV_EXPORTS_W CharucoBoard : public Board {
177179
CV_WRAP static Ptr<CharucoBoard> create(int squaresX, int squaresY, float squareLength,
178180
float markerLength, const Ptr<Dictionary> &dictionary);
179181

180-
CV_WRAP Size getChessboardSize() const { return Size(_squaresX, _squaresY); }
181-
CV_WRAP float getSquareLength() const { return _squareLength; }
182-
CV_WRAP float getMarkerLength() const { return _markerLength; }
183-
184-
private:
185-
void _getNearestMarkerCorners();
182+
CV_WRAP Size getChessboardSize() const;
183+
CV_WRAP float getSquareLength() const;
184+
CV_WRAP float getMarkerLength() const;
186185

187-
// number of markers in X and Y directions
188-
int _squaresX, _squaresY;
189-
190-
// size of chessboard squares side (normally in meters)
191-
float _squareLength;
192-
193-
// marker side length (normally in meters)
194-
float _markerLength;
186+
protected:
187+
struct CharucoImpl;
188+
Ptr<CharucoImpl> charucoImpl;
195189
};
196190

197191
/**

modules/aruco/src/board.cpp

Lines changed: 78 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,15 @@ float GridBoard::getMarkerSeparation() {
200200
return gridImpl->markerSeparation;
201201
}
202202

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>()) {}
203212

204213
void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int borderBits) {
205214
CV_Assert(!outSize.empty());
@@ -212,8 +221,8 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
212221
out.colRange(marginSize, out.cols - marginSize).rowRange(marginSize, out.rows - marginSize);
213222

214223
double totalLengthX, totalLengthY;
215-
totalLengthX = _squareLength * _squaresX;
216-
totalLengthY = _squareLength * _squaresY;
224+
totalLengthX = charucoImpl->squareLength * charucoImpl->sizeX;
225+
totalLengthY = charucoImpl->squareLength * charucoImpl->sizeY;
217226

218227
// proportional transformation
219228
double xReduction = totalLengthX / double(noMarginsImg.cols);
@@ -233,21 +242,21 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
233242

234243
// determine the margins to draw only the markers
235244
// 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));
238247

239-
double diffSquareMarkerLength = (_squareLength - _markerLength) / 2;
248+
double diffSquareMarkerLength = (charucoImpl->squareLength - charucoImpl->markerLength) / 2;
240249
int diffSquareMarkerLengthPixels =
241-
int(diffSquareMarkerLength * squareSizePixels / _squareLength);
250+
int(diffSquareMarkerLength * squareSizePixels / charucoImpl->squareLength);
242251

243252
// draw markers
244253
Mat markersImg;
245254
_drawPlanarBoardImpl(this, chessboardZoneImg.size(), markersImg, diffSquareMarkerLengthPixels, borderBits);
246255
markersImg.copyTo(chessboardZoneImg);
247256

248257
// 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++) {
251260

252261
if(y % 2 != x % 2) continue; // white corner, dont do anything
253262

@@ -263,15 +272,67 @@ void CharucoBoard::draw(Size outSize, OutputArray _img, int marginSize, int bord
263272
}
264273
}
265274

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+
266327
Ptr<CharucoBoard> CharucoBoard::create(int squaresX, int squaresY, float squareLength,
267328
float markerLength, const Ptr<Dictionary> &dictionary) {
268329
CV_Assert(squaresX > 1 && squaresY > 1 && markerLength > 0 && squareLength > markerLength);
269330
Ptr<CharucoBoard> res = makePtr<CharucoBoard>();
270331

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;
275336
res->dictionary = dictionary;
276337

277338
float diffSquareMarkerLength = (squareLength - markerLength) / 2;
@@ -306,62 +367,15 @@ Ptr<CharucoBoard> CharucoBoard::create(int squaresX, int squaresY, float squareL
306367
}
307368
res->rightBottomBorder = Point3f(squaresX * squareLength,
308369
squaresY * squareLength, 0.f);
309-
res->_getNearestMarkerCorners();
310-
370+
_getNearestMarkerCorners(*res, res->charucoImpl->squareLength);
311371
return res;
312372
}
313373

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); }
320375

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; }
365379

366380
bool testCharucoCornersCollinear(const Ptr<CharucoBoard> &_board, InputArray _charucoIds) {
367381
unsigned int nCharucoCorners = (unsigned int)_charucoIds.getMat().total();

0 commit comments

Comments
 (0)