Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

aruco::detectMarkers is not finding true edges of markers

Tags:

opencv

aruco

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:

Marker board

Here's the detail of the lower-left marker showing the inaccuracy of the edge detection:

Lower-left marker

Here's the detail of the upper-right marker showing an accurate edge detection of the same marker ID:

enter image description here

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.
}
like image 405
SSteve Avatar asked Dec 09 '16 01:12

SSteve


People also ask

How are ArUco markers detected?

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.

What is ArUco marker ID?

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.


1 Answers

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!

Edges correctly identified

like image 192
SSteve Avatar answered Sep 28 '22 01:09

SSteve