pythonopencvaruco

How can I get the distance from my camera to an OpenCV ArUco Marker


How can I use the ArUco Framework from OpenCV to get the distance from the camera to the ArUco Marker?


Solution

  • There are several steps required to get the distance from your camera to the ArUco Marker.

    Calibrate the camera

    This step is of most importance. If you skip this one, all results in the further described steps will not be accurate.

    The camera you will be using will need to be calibrated. It is of importance that you use the camera for this step in the same exact way you will be using it for the marker detection. So same resolution, focal length (same lense).

    There are a lot of good guides out there so I will skip this task to focus on the main question. Possible guides: https://docs.opencv.org/master/da/d13/tutorial_aruco_calibration.html https://mecaruco2.readthedocs.io/en/latest/notebooks_rst/Aruco/Projet+calibration-Paul.html

    Receive distance from camera to ArUco marker

    This step requires the parameters to correct the distortion from the previous step. I will be calling the cameraMatrix mtx and the distCoeffs dist in the further examples.

    1. Make sure that you adjust all the parameters needed for the ArUco detection.

    I won't explain what is needed for the simple marker detection as there are a lot of good guides out there.

    dictionary = cv.aruco.Dictionary_get(cv.aruco.DICT_4X4_50)
    parameters = cv.aruco.DetectorParameters_create()
    
    1. Search for makers on your frame

    frame will be your frame containing the marker

    (corners, ids, rejected) = cv.aruco.detectMarkers(frame, dictionary, parameters=parameters)
    
    1. Estimate the pose of the marker

    You will need the size of the marker you want to find. So the actual real life size printed of it on the paper. Measure it as we will be needing it. It doesn't matter what measuring unit you will use. But be aware as the result of the distance we will receive will be the same unit. I used CM in this e.g.

    markerSizeInCM = 15.9
    rvec , tvec, _ = aruco.estimatePoseSingleMarkers(corners, markerSizeInCM, mtx, dist)
    
    1. Read out Distance

    We now have the rotation vector of the marker (rvec) relative to the camera and the translation vector (tvec). See source: OpenCV

    The translation vector is in the same unit we provided the real marker size of in step 3. It is in the format [x,y,z] which is the position of the marker in the 3D space.

    We now only need to read out z from the tvec which will be the distance from our camera to the marker center in the same measuring unit we provided in step 3.