# AprilTag 3: a C fiducial detector for robotics, and where it stops being the right tool

> AprilTag 3 is a small C library with minimal dependencies that detects printed square markers and estimates their pose. It is well suited to robotics work where you control the markers, and awkward when you need a general-purpose barcode reader.

**AprilRobotics/apriltag** — AprilTag is a visual fiducial system popular for robotics research.

- Repository: https://github.com/AprilRobotics/apriltag
- Website: https://april.eecs.umich.edu/software/apriltag
- Stars: 2,543 · Forks: 680
- Language: C
- License: NOASSERTION
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/aprilrobotics-apriltag

## The problem AprilTag 3 solves, and who it is aimed at

AprilTag is a visual fiducial system: you print a square marker on paper or a board, point a camera at it, and a program tells you which marker it is and where it sits in 3D. The repository holds AprilTag 3, described in the README as including "a faster (>2x) detector, improved detection rate on small tags, flexible tag layouts, and pose estimation". The intended reader is someone building a robot, a calibration rig, or an augmented reality setup where the markers are under their control. The library is C with, in the README's words, "minimal dependencies", which matters when the detector has to run on a board that cannot afford a large vision framework. The README points to tag images in a separate repository and recommends the tagStandard41h12 layout for most applications. That recommendation is a useful signal: the project has an opinion about defaults rather than presenting every family as equally good.

## How detection works: quads, families, and pose

The pipeline is visible in the file layout. apriltag_quad_thresh.c handles the thresholding and quad detection step, apriltag.c holds the detector itself, and apriltag_pose.c plus apriltag_pose.h cover pose estimation. Each tag family has its own generated pair of files, for example tagStandard41h12.c and tagStandard41h12.h, and the repository ships families including tag16h5, tag25h9, tag36h10, tag36h11, tagCircle21h7, tagCircle49h12, tagCustom48h12, tagStandard41h12 and tagStandard52h13, plus an aruco/ directory for the ArUco families.

The data flow is: an image_u8_t grayscale buffer goes in, the detector finds candidate quadrilaterals, decodes the payload against the family you registered, and returns a zarray_t of detections. In C you create a detector, create a family, add the family to the detector, and call apriltag_detector_detect. The README notes that image data in a cv::Mat can be passed "without creating a deep copy" by building an image_u8_t header over the Mat buffer, which is the detail that makes this library usable inside an existing OpenCV pipeline rather than beside it. The README also states that the library itself has no external dependencies, but that most applications will need a method for acquiring images, so the camera layer is yours to supply.

Tuning is exposed rather than hidden. quad_decimate trades speed against detection distance, nthreads uses extra cores, quad_sigma helps on noisy images, and decode_sharpening is the knob to experiment with once the tag border is being found. The README suggests running with debug=1 to generate debug images showing the output at each stage of the pipeline, which is the intended way to work out which stage is failing.

## Installing AprilTag 3 and detecting your first tag

The README says only Linux is officially supported, though users have reported success on Windows. The default install puts headers in /usr/local/include, the shared library in /usr/local/lib, a pkg-config script in /usr/local/lib/pkgconfig, and a Python wrapper if python3 is present. Build with CMake:

```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --target install
```

This produces shared libraries by default. If you need static libraries, set BUILD_SHARED_LIBS to OFF. If Ninja is installed, the README gives a variant that adds -GNinja to the configure step and notes it is much faster than the default Makefile generator. You can drop --target install if you only want to use the build locally. The build also produces the OpenCV example, which the README says you can run as ./build/opencv_demo.

With the Python wrapper installed, the README gives this example:

```python
import cv2
import numpy as np
from apriltag import apriltag

imagepath = 'test.jpg'
image = cv2.imread(imagepath, cv2.IMREAD_GRAYSCALE)
detector = apriltag("tagStandard41h12")

detections = detector.detect(image)
```

The image is loaded as grayscale, the detector is constructed with a family name string, and detect returns a list of detections. The README also mentions an alternative set of Python bindings maintained by duckietown, so if the bundled wrapper does not fit your project there is a second option. Before any of this you need a marker: the README points to the apriltag-imgs repository for pre-generated layouts and says to scale the images up and print them.

## Where AprilTag 3 is the wrong choice

The biggest constraint is that a detector instance is tied to a tag family. You create the detector with a family such as tagStandard41h12, and the README's guidance is to pick one family up front based on your needs: tagStandard52h13 when you need more tags, tagCircle49h12 or tagCircle21h7 when you need to fit a small circular object, tagCustom48h12 for recursive tags. If your scene contains markers from two families, the README does not describe a single call that handles both, and the C API example adds one family to one detector. You can work around this by registering more than one family, but that is not what the getting-started material shows, and it is the kind of thing to confirm against the headers before you commit to a design.

The second constraint is that this is a build-from-source C library. There is no package manager install in the README, no prebuilt binary, and no managed runtime. If your team cannot compile C or does not want to own a shared library in /usr/local/lib, the bundled Python wrapper still depends on that build step. The README's install section is the whole story: CMake, then install. The third constraint is upgrading from AprilTag 2. The README calls it a drop-in replacement for most use cases, but notes that refine_decode, refine_pose and black_border have been removed, and that if you generated your own families you must regenerate the C code for them. The Java code, it says, does not need regenerating. Removed options mean any configuration that referenced them has to be rewritten, not merely recompiled. Finally, the README does not document rollback, version pinning, or what changes between the 3.4.x releases, so treat upgrade risk as something you verify yourself.

## AprilTag compared with ArUco and with QR codes

The most common comparison is AprilTag against ArUco. The difference in approach is that ArUco is part of OpenCV and arrives with it, while AprilTag 3 is a separate C library that you build and link. If your project already depends on OpenCV, ArUco is the path of least resistance because there is nothing extra to install. AprilTag 3's counterargument is the dependency posture: the README states the library has no external dependencies, which is a real difference when the target device is a small embedded board and OpenCV is too large to carry. AprilTag 3 also now integrates the native ArUco families, so tagAruco4x4_50, tagAruco5x5_100, tagAruco6x6_250 and tagAruco7x7_1000 can be detected through AprilTag's own detector. That makes the choice less about marker format and more about which detector and build you want to maintain.

Against QR codes, the distinction is purpose. QR codes are designed to carry arbitrary data and to be read by general-purpose scanners; AprilTag markers are designed to be found reliably and to yield a pose. The README's tuning section is about detection distance, quad decimation and decode sharpening, which is the vocabulary of a pose-tracking system, not a data-transfer format. If you need to encode a URL, QR is the right tool and AprilTag is not.

## Maintenance, releases and licence

The repository is not archived, and the last push was on 2026-08-07. Recent releases are v3.4.5 on 2025-08-29, v3.4.4 on 2025-07-26, and v3.4.3 on 2025-02-16. The gap between the 3.4.3 and 3.4.4 releases is roughly five months, and the two most recent releases are about a month apart, so release cadence has not been uniform. The README does not describe a deprecation policy or a support window, and the upgrade notes for AprilTag 2 are the closest thing to a migration document.

The licence is listed as NOASSERTION, which means the repository's licence could not be classified automatically. The LICENSE.md file is present at the top level, so the terms exist, but you should read that file rather than infer anything from the label. Nothing here should be read as legal advice. The practical implication is that before shipping AprilTag 3 inside a product, someone on your side needs to open LICENSE.md and confirm the terms match how you intend to distribute, particularly if you are linking the static library rather than the shared one.

## Conclusion

Adopt AprilTag 3 if you print your own markers and need pose estimation from a C library you can link into an existing vision pipeline. Do not adopt it if you need to read arbitrary markers in the wild or want a managed runtime. Before committing, verify that your camera driver gives you a grayscale buffer you can wrap in image_u8_t without a copy, and check which tag family your printed images actually belong to, because the detector is created for one family at a time.

## FAQ

### What are AprilTags used for?

AprilTag is a visual fiducial system popular in robotics research. You print a tag image, point a camera at it, and the detector reports the tag identity and its pose, which is why the README groups pose estimation alongside detection.

### Who invented AprilTags?

The README links to papers hosted at the University of Michigan, including the original AprilTag paper by Olson and the AprilTag 2 paper by Wang, and the project homepage is on the umich.edu domain.

### How do I install apriltag?

Configure with cmake -B build -DCMAKE_BUILD_TYPE=Release and then run cmake --build build --target install. The README says only Linux is officially supported, and that this places headers in /usr/local/include and the shared library in /usr/local/lib.

### What is apriltag detection?

It is the process of finding tag quadrilaterals in a grayscale image and decoding them against a registered tag family, returning a list of detections. In the Python example the detector is created for one family, such as tagStandard41h12, and detect returns the results.

### What is the difference between apriltag and aruco marker detection?

ArUco ships inside OpenCV, while AprilTag 3 is a separate C library that the README says has no external dependencies. AprilTag 3 also integrates the native ArUco families such as tagAruco4x4_50 and tagAruco5x5_100, so you can detect ArUco markers through AprilTag's detector.

## Sources

- [AprilRobotics/apriltag on GitHub](https://github.com/AprilRobotics/apriltag)
- [Issues](https://github.com/AprilRobotics/apriltag/issues)
- [Project website](https://april.eecs.umich.edu/software/apriltag)
- [README](https://github.com/AprilRobotics/apriltag/blob/master/README.md)
- [Releases](https://github.com/AprilRobotics/apriltag/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/aprilrobotics-apriltag
