I'm using ArUco markers to correct perspective and calculate sizes in an image. In this image I know the exact distance between the outer edges of the markers and am using that to calculate the sizes of the black rectangles.
My problem is that aruco::detectMarkers
doesn't always identify the true edges of the markers (as shown in the detail image). When I correct the perspective based on the corners of the markers, it causes distortion that affects the size calculations of the objects in the image.
Is there a way to improve the edge detection accuracy of aruco::detectMarkers
?
Here's a scaled-down photo of the entire board:
Here's the detail of the lower-left marker showing the inaccuracy of the edge detection:
Here's the detail of the upper-right marker showing an accurate edge detection of the same marker ID:
It's hard to see in this shrunken image but the upper-left marker is accurate and the lower-right marker is inaccurate.
My function that calls detectMarkers
:
bool findMarkers(const Mat image, Point2d outerMarkerCoordinates[], Point2d innerMarkerCoordinates[], Size2d *boardSize) {
Ptr<aruco::Dictionary> theDictionary = aruco::getPredefinedDictionary(aruco::DICT_4X4_1000);
vector<vector<Point2f> > markers;
vector<int> ids;
aruco::detectMarkers(image, theDictionary, markers, ids);
aruco::drawDetectedMarkers(image, markers, ids);
return true; //There's actually more code here that makes sure there are four markers.
}
Detecting ArUco markers with OpenCV is a three-step process: Set what ArUco dictionary you are using. Define the parameters to the ArUco detector (typically the default options suffice). Apply the ArUco detector with OpenCV's cv2.
An ArUco marker is a synthetic square marker composed by a wide black border and an inner binary matrix which determines its identifier (id). The 4X4 corresponds to the inner binary grid, the id 0 is the specific data within that grid, and the 50 is the size of the marker in pixels.
Examination of the optional detectorParameters
argument to detectMarkers
showed a parameter called doCornerRefinement
. Its description is "do subpixel refinement or not". Since the error I'm seeing is larger than a pixel, I didn't think this was applicable to my situation. I gave it a try anyway and experimented with the cornerRefinementWinSize
value and found that it did indeed solve my problem. Now I'm thinking that "pixel" in the ArUco sense is the size of one of the squares within the marker, not an image pixel.
The modified call to detectMarkers
:
bool findMarkers(const Mat image, Point2d outerMarkerCoordinates[], Point2d innerMarkerCoordinates[], Size2d *boardSize) {
Ptr<aruco::Dictionary> theDictionary = aruco::getPredefinedDictionary(aruco::DICT_4X4_1000);
vector<vector<Point2f> > markers;
vector<int> ids;
Ptr<aruco::DetectorParameters> detectorParameters = new aruco::DetectorParameters;
detectorParameters->doCornerRefinement = true;
detectorParameters->cornerRefinementWinSize = 11;
aruco::detectMarkers(image, theDictionary, markers, ids, detectorParameters);
aruco::drawDetectedMarkers(image, markers, ids);
return true; //There's actually more code here that makes sure there are four markers.
}
Success!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With