Before obtaining the camera pose using the detected markers, it is necessary to know the calibration parameters of the camera. In this sense, ArUco provides the necessary calibration procedures to perform this task. Note that the calibration procedure is only performed once because the camera optics are not modified. The main function to use in the calibration process is cv2.aruco.calibrateCameraCharuco().
The aforementioned function calibrates a camera using a set of corners from several views extracted from a board. When the calibration process is finished, this function returns the camera matrix (a 3 x 3 floating-point camera matrix) and a vector containing the distortion coefficients. More specifically, the 3 x 3 matrix encodes both the focal distances and the camera center coordinates (also known as intrinsic parameters). The distortion coefficients model the distortion produced by the camera.
The signature of the function is as follows:
calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]]) -> retval, cameraMatrix, distCoeffs, rvecs, tvecs
Here, charucoCorners is a vector containing the detected charuco corners, charucoIds is the list of identifiers, board represents the board layout, and imageSize is the input image size. The output vector, rvecs, contains a vector of rotation vectors estimated for each board view and tvecs is a vector of translation vectors estimated for each pattern view. As previously commented, the camera matrix, cameraMatrix, and the distortion coefficients, distCoeffs, are also returned.
The board is created using the cv2.aruco.CharucoBoard_create() function:
The signature is as follows:
CharucoBoard_create(squaresX, squaresY, squareLength, markerLength, dictionary) -> retval
Here, squareX is the number of squares in the x direction, squaresY is the number of squares in y direction, squareLength is the chessboard square side length (normally in meters), markerLength is the marker side length (same units as squareLength), and dictionary sets the first markers in the dictionary to use in order to create the markers inside the board. For example, in order to create a board, we can use the following lines of code:
dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_7X7_250)
board = cv2.aruco.CharucoBoard_create(3, 3, .025, .0125, dictionary)
img = board.draw((200 * 3, 200 * 3))
The created board can be seen in the next screenshot:
This board will be later used by the cv2.aruco.calibrateCameraCharuco() function in the calibration process:
cal = cv2.aruco.calibrateCameraCharuco(all_corners, all_ids, board, image_size, None, None)
Once the calibration process has been finished, we will save both the camera matrix and the distortion coefficients to disk. To do so, we use pickle, which can be used for serializing and de-serializing a Python object structure.
After the calibration procedure has been finished, we can now perform camera pose estimation.
The aruco_camera_calibration.py script carries out the calibration procedure. Note that this script can be used to both create the board and perform the calibration procedure, by making use of the previously created and printed board.