OpenCV - Improving marker detection on Charuco board

Viewed 589

I am using OpenCV's aruco::CharucoBoard object for calibration purposes and noticed that its marker detection doesn't find all visible markers/corners in the images.

I started investigate the matter and tried to detect the markers on the image of the board that was printed for the calibration. The aruco::detectMarkers fails to detect all markers unless the image size is 640x480. I'm sure that some tweaking in the aruco::DetectorParameters is required, but I've yet to find the optimal values.

Here is the relevant code:

int nx = 16;
int ny = 10;
double sqrLength = 1.0;
double markerLength = 0.8;
    
Ptr<aruco::Dictionary> dictionary = aruco::getPredefinedDictionary(aruco::DICT_6X6_250);
Ptr<aruco::CharucoBoard> board = aruco::CharucoBoard::create(nx, ny, sqrLength, markerLength, dictionary);
aruco::DetectorParameters params = aruco::DetectorParameters::create();

Mat boardImg;
Size boardImgSize = Size(640 * 2, 480 * 2);
board->draw(boardImgSize, boardImg);

vector<int> markerIds;
vector<vector<Point2f>> markerCorners, rejected;
aruco::detectMarkers(boardImg, board->dictionary, markerCorners, markerIds, params, rejected);
 cout << markerIds.size() << endl;
    aruco::drawDetectedMarkers(boardImg, markerCorners);
imshow("board", boardImg);
waitKey(30);

The total number of markers on the board is 80 and the above code manages to find all of them only for Size boardImgSize = Size(640, 480)

Any idea on how to improve the detection/which parameters should be tweaked?

1 Answers

First of all it looks like the total number of markers on the board should be 160: nx * ny = 16 * 10 = 160.

But the reason of your issue is related to incorrect sqrLength and markerLength parameter values. As you may find at https://docs.opencv.org/4.5.0/d0/d3c/classcv_1_1aruco_1_1CharucoBoard.html#aa83b0a885d4dd137a41686991f85594c (create() description):

squareLength is a chessboard square side length (normally in meters)

markerLength is a marker side length (same unit than squareLength)

So you should provide values in meters which are measured from printed pattern.

Best choice for your case is to measure square side length and marker side length and set this to sqrLength and markerLength. For example, if your pattern was printed on paper 1x1m values will be: sqrLength = PatternWidth / nx = 1 / 16 = 0.0625 markerLength = sqrLength * 0.8 = 0.0625 * 0.8 = 0.05

Related