AruCo Marker Distance in TVEC is wrong

Hello,
I am currently working on an algorithm to use ArUco Markers to calculate the exact position of my camera in real world coordinate system with the center of the ArUco Marker beeing the coordinate (0,0,0).
The problem is that that while I use a 20cm big marker. The calculated distance of my marker is quite high. And I dont seem to find a way to fix it.
Ive calibrated my camera beforehand with around 200 images of a charuco board.

tvec[0]: 0.245 m,
tvec[1]: 0.035 m,
tvec[2]: 0.809 m

The real distance to the marker is 0.84m (measured with a ruler)

Especially when rotation to the camera is applied the distance measurements are getting way worse. I am also calculating the rotations with the help of the rodrigues function and those seem pretty accurate.

Code for reference (shortened version):

port = 0
marker_length_in_m = 0.2

cap = cv2.VideoCapture(port + cv2.CAP_DSHOW)

aruco_dict = aruco.Dictionary_get(aruco.DICT_4X4_50)
para = aruco.DetectorParameters_create()
para.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_SUBPIX

while True:
    ret, frame = cap.read()
    if kinectV2:
        frame = cv2.flip(frame, 1)  # Kinect V2 has the wrong orientation

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # grayscale for easier detection

    corners, ids, rejectedImgPoints = aruco.detectMarkers(  # detect markers to get corners and ids
        gray, aruco_dict, parameters=para)

    aruco.drawDetectedMarkers(frame, corners, ids)

    rvecs_n, tvecs_n, _ObjectPoints = aruco.estimatePoseSingleMarkers(
        corners=corners,
        markerLength=marker_length_in_m,
        cameraMatrix=mtx,
        distCoeffs=dist,
        rvecs=rvecs,
        tvecs=tvecs)

    if ids is not None:
        aruco.drawAxis(frame, mtx, dist, rvecs_n, tvecs_n, marker_length_in_m)

    cv2.imshow("frame", frame)

    if cv2.waitKey(1) == ord('y'):  # save on pressing 'y'
        if ids is not None:
            # estimation of pose via rotation vector and translation vector
            rvecs_n, tvecs_n, _ObjectPoints = aruco.estimatePoseSingleMarkers(
                corners=corners,
                markerLength=marker_length_in_m,
                cameraMatrix=mtx,
                distCoeffs=dist,
                rvecs=rvecs,
                tvecs=tvecs)

I don’t see the problem. looks reasonable to me.

remember, that pose is the marker’s pose in the camera’s frame (i.e. it transforms marker-space points to camera-space points).

if you want the camera’s position in marker space, you need to invert the transformation.

@crackwitz Is a 3cm difference between measurement and realworld an excpected deviation? Considering this is quite close and with a big marker size that seems rather high…

Thanks for the tip with the invertion of the transformation

0.809 is merely the Z component, not the euclidean distance.

you could have calculated the length of your tvec. it’s 0.846… or you could have moved the camera so the marker’s center is in the view’s center. then x and y are closer to 0.

if you round your distances to centimeters, of course you’ll get differences of several millimeters.

I’m still puzzled what made you originally state “The calculated distance of my marker is quite high” and would very much like to hear why you said that.

further potential sources of “error”:

  • guess where the camera’s optical center is… doesn’t have to be the center of the lens, could be ahead or behind
  • your calibration might be bad (or okay). reprojection error doesn’t say much if your data is junk.
  • did you measure your aruco marker’s length in both directions? how accurate do you expect your printer to be?

what kinda accuracy do you need? with what kind of accuracy have you been working? what accuracy do your measuring instruments have?

Thanks a lot for the reply.

I’m still puzzled what made you originally state “The calculated distance of my marker is quite high” and would very much like to hear why you said that.

I assumed that the z component equals the distance from the marker middle to the camera, because in a lot of posts it is referenced this way (at least from what I understood).
Thats why I was puzzled by a deviation of 3cm.

I will definitly check out the sources for error.
I did measure my marker in both directions with a standard ruler so I expect an error of around one or two milimeter.

what kinda accuracy do you need? with what kind of accuracy have you been working? what accuracy do your measuring instruments have?

I want to use the calibration for several cameras later for 3D Reconstruction on thus a accuracy to the milimeter would be great.
If you could elaborate what you mean with “what accuracy have i been working with”.
In terms of accuracy of measuring instruments i use standard rulers, so I basically have a lot deviation. Especially considering the optical center of the camera is unknown/guess by me.

I haven’t needed super accurate calibrations so I can’t say much about it.

be wary of calibrations with good reprojection error. that might be a good calibration, or not. good reprojection error doesn’t imply the calibration is good. it just means the data could be fitted well. the data might be bad.

the marker’s pose is expressed in the camera’s frame. the translation component’s z literally goes along the camera’s optical axis. x and y go away from the optical axis, in a plane that is normal to the optical axis.

as for accuracy… look up the book “Foundations of Mechanical Accuracy”. tl;dr: drop an order of magnitude every time you transfer measurements from one object to another. good rule of thumb.

1 Like