I'm using OpenCV's Aruco module in Python to detect my AprilTag calibration board. The problem is that only very few markers get detected, despite a rather good input image. From everything I tried, it seems that the AprilTag implementation is very sensitive and requires an almost ideal image to work. If this really is the case, that would make OpenCV's AprilTag detector almost unusable.
I'm using:
First of all a minimal code example (following the OpenCV Aruco module documentation):
import cv2
img = cv2.imread("april_board_drawing.png", cv2.IMREAD_COLOR)
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11)
arucoParams = cv2.aruco.DetectorParameters()
arucoParams.markerBorderBits = 2
(corners, ids, rejected) = cv2.aruco.detectMarkers(img, aruco_dict, parameters=arucoParams)
cv2.aruco.drawDetectedMarkers(img, corners, ids)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
I started out with an "ideal" image to test whether the tags get detected correctly and that there is no mismatch between my calibration board and the AprilTag dictionary. This worked out nicely, all markers were detected.
I then proceeded with a recording from my camera. And here the problem ocurred. Only very few markers got detected (15/49). I chose one of the best images I took for this. Not all markers are perfect, there is some glare, but many have quite good contrast and are still not detected. I played around with the detection parameters, with no luck.
Maybe the distortion is too strong I thought. So I rectified the image, thereby removing the distortion and tried again. This got me some additional detections (20/49), but many where still not detected.
I then had a look at the rejected markers. They seem to be rejected correctly. No issue there. Although, it is weird that multiple markers are almost correct. Not sure what's going on there. I specified the correct border size.
Other things I tried:
I'm reluctant to experiment with adaptive contrast enhancement, since I expect the algorithm to work with this level of image quality. Are my expectations too high?
The geometry of the calibration board doesn't seem to be a problem, since the markers are detected correctly in the ideal drawing, right? I prefer using this type of board, due to its high marker density and the ability to perform subpixel refinement on the corners.
Any idea what's going wrong here? Any help is very much appreciated!
Here are all input images I used:
If you parameterize the aruco detector differently, you can detect more codes. It is most probable due the adaptive thresholding. If you change the default of arucoParams.adaptiveThreshWinSizeStep=10
to a smaler value, the detector detects more codes. I achived the best results (distorted: 48/49, undistorted: 47/49) with the parameter choice:
arucoParams = cv2.aruco.DetectorParameters()
arucoParams.markerBorderBits = 2
params.adaptiveThreshWinSizeStep = 1
When you change the default parameter arucoParams.minMarkerDistanceRate
to arucoParams.minMarkerDistanceRate = 0.0
, the detector detects in the undistorted image 1 tag more, but the detector result includes multiple detections for each tag.