Inconsistent orientation of detected/generated ArUco and AprilTags · Issue #1195 · opencv/opencv-python · GitHub
Skip to content

Inconsistent orientation of detected/generated ArUco and AprilTags #1195

Open

Description

@qian-chu

ArUco and AprilTag detection both uses a clockwise orientation, however, AprilTag corners start with bottom right while ArUco starts with upper left. See the example below:

Image Image

Code:

import cv2


def draw_markers_with_corners(img, corners):
    for i, marker_corners in enumerate(corners):
        # Get the corners of the marker
        corner_points = marker_corners.reshape((4, 2))
        corner_points = corner_points.astype(int)

        # Draw each corner with its ordinal position
        for j, corner in enumerate(corner_points):
            # Draw corner point
            cv2.circle(img, tuple(corner), 5, (0, 0, 255), -1)
            # Label the corner with its ordinal position (0, 1, 2, 3)
            cv2.putText(
                img,
                str(j),
                (corner[0] + 10, corner[1] + 10),
                cv2.FONT_HERSHEY_SIMPLEX,
                0.5,
                (255, 0, 0),
                2,
            )

    return img


img = cv2.imread("markers.jpeg")

parameters = cv2.aruco.DetectorParameters()

april_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11)
april_detector = cv2.aruco.ArucoDetector(april_dict, parameters)
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250)
aruco_detector = cv2.aruco.ArucoDetector(aruco_dict, parameters)

img_marked = img.copy()
april_corners, _, _ = april_detector.detectMarkers(img)
img_marked = draw_markers_with_corners(img_marked, april_corners)

aruco_corners, _, _ = aruco_detector.detectMarkers(img)
img_marked = draw_markers_with_corners(img_marked, aruco_corners)

cv2.imwrite("markers_detected.jpeg", img_marked)

The same issue persists (likely due to pre-defined dictionary configurations) for generation:

The generated AprilTag 36h11 - 0 (wrong orientation, see above)
Image

The generated ArUco 4x4_250 - 0 (correct orientation, see above)
Image

Code:

import cv2

april_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36h11)
aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250)

img = cv2.aruco.generateImageMarker(aruco_dict, 0, 200, borderBits=1)
cv2.imwrite("aruco.png", img)

img = cv2.aruco.generateImageMarker(april_dict, 0, 200, borderBits=1)
cv2.imwrite("april.png", img)

Activity

  1. s-trinh commented on Jan 28, 2026

    @s-trinh

    The generated image uses: https://github.com/opencv/opencv/blob/55a8996ffe660444b0a3c268c967f67b133ab332/modules/objdetect/src/aruco/apriltag/predefined_dictionaries_apriltag.hpp#L11961-L11966

    { {33, 161, 70, 186, 11},

    33 in decimal gives in binary: 0010 0001
    161 in decimal gives in binary: 1010 0001


    In my opinion, the following should be tested/verified:

    • what is the convention about the corners order in the official AprilTag repo?
    • does the current output/convention match the AprilTag repo?
    • what is the consequence about the estimated tag pose?
    • code breaking change? add a parameter for that?
  2. s-trinh commented on Jan 29, 2026

    @s-trinh

    AprilTag official repository

    Using the opencv_demo.cc in the AprilTag repository, it gives the following corners order:

    Image

    You can use this tool to generate the marker images:

    Regeneration of the AprilTag codeword

    I have regenerated the AprilTag codeword in order to try to match the ArUco convention:

    It seems to work.

    25h9

    Image

    36h11

    Image

    Tag image generation

    Using your Python script and with the following parameters, it gives for:

    • 36h11, id=46
    Image
  3. qian-chu commented on Feb 13, 2026

    @qian-chu
    Author

    AprilTag official repository

    Using the opencv_demo.cc in the AprilTag repository, it gives the following corners order:

    Image You can use this tool to generate the marker images:

    Regeneration of the AprilTag codeword

    I have regenerated the AprilTag codeword in order to try to match the ArUco convention:

    It seems to work.

    25h9

    Image #### 36h11 Image ### Tag image generation Using your Python script and with the following parameters, it gives for:
    • 36h11, id=46
    Image

    Thanks so much for trying out! This looks great to me. I would personally love to see your branch merged to fix the issue for good. For me personally, I have a workaround to simply re-order the detected corners for AprilTags for now. Up to you how you would like to proceed.

  4. added a commit that references this issue on Jun 4, 2026
  5. added a commit that references this issue on Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions