Aruco detector not providing subpixel accuracy
As an example example, I generated this 3x2 Charuco board and annotated the fiducials, I get the following positions for each corner (order of fiducials is provided by Aruco detector opencv method)
10 60
39 60
39 89
10 89
60 10
89 10
89 39
60 39
However the correct positions are
9.5 59.5
39.5 59.5
39.5 89.5
9.5 89.5
59.5 9.5
89.5 9.5
89.5 39.5
59.5 39.5
I understand that for plotting it is required to round to the nearest integer, but still Aruco detector return floating point values without the decimal part (i.e 60.0). Also, it is not a matter of adding 0.5 to every coordinate since some of them require +0.5, and other -0.5. I tried Apriltag corner refinement but seems to be doing alright, not sure if needs additional parameters.
I would appreciate if you could help me with that, cause this is not even a real life picture, this is the cleanest case where the accuracy by default should be optimal
The code to generate the image is
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# Generate
num_squares_x = 3
num_squares_y = 2
square_width_m = 5
marker_width_m = 3
dictionary_id = cv.aruco.DICT_6X6_250
dictionary = cv.aruco.getPredefinedDictionary(cv.aruco.DICT_6X6_250)
board = cv.aruco.CharucoBoard((num_squares_x, num_squares_y), square_width_m, marker_width_m, dictionary)
image = board.generateImage((num_squares_x*50, num_squares_y*50)) # this will generate 150x100
# Detect
aruco_params = cv.aruco.DetectorParameters()
aruco_detector = cv.aruco.ArucoDetector(dictionary, aruco_params)
marker_corners, marker_ids, rejected_ids = aruco_detector.detectMarkers(image)
# Annotate (using cross marker)
image_annotated = cv.cvtColor(image, cv.COLOR_GRAY2BGR)
id = 0
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 20, 0.001)
for corners in marker_corners:
for corner in corners[0]:
curr_position = (int(corner[0]), int(corner[1]))
cv.drawMarker(image_annotated, position=curr_position, color=(255,0,0), markerType=cv.MARKER_CROSS, markerSize=3, thickness=1) # Red filled circles
cv.putText(image_annotated, str(id), (curr_position[0]+2,curr_position[1]+2), cv.FONT_HERSHEY_SIMPLEX, fontScale=0.3, color=(0,255,0), thickness = 1)
id += 1
plt.imshow(image_annotated)
plt.show()