Generate flush black/white ArUco labels as Bambu Studio 3MF files for AMS multi-color printing. Built for printing fiducials to attach to a headband as 6-DOF ground truth while recording OpenTrack NeuralNet training data.
Each label is a flat slab whose readable face is a single Z plane: black and white cells are coplanar — flush, no step. A solid white backing ties the isolated white cells together and keeps the label rigid and planar (which is what makes the ArUco corner/pose estimate accurate). The 3MF opens with two color bodies pre-assigned to filament 1 = black, filament 2 = white.
pixi run generate # full starter set: 7 markers (ids 0-6) + P1S board
pixi run aruco # just the 7 headband markers
pixi run charuco # just the ChArUco board
pixi run python arucogen.py --ids 0-7 --size 50
pixi run python arucogen.py --dict 5x5_100 --ids 0,3,9 --quiet-cells 1.5
pixi run python arucogen.py --charuco # ChArUco board, 208mm (P1S plate + purge-tower room)Output lands in out/: one *.3mf per id plus a *_preview.png showing the
true marker (as a camera sees it) for verification.
Key options (--help for all):
| flag | default | meaning |
|---|---|---|
--dict |
4x4_50 |
ArUco dictionary (5x5_100, 6x6_250, apriltag_36h11, …) |
--ids |
0-4 |
ids as a range 0-4 and/or list 0,3,7 |
--size |
60 |
marker edge in mm (incl. black border, excl. quiet zone) |
--quiet-cells |
1 |
white quiet-zone ring width, in marker cells (0 disables) |
--thickness |
1.5 |
total slab thickness in mm |
--face-thickness |
0.6 |
thickness of the colored face layers in mm |
--charuco emits a single ChArUco calibration board instead of markers. The
default is an 8×8 board of 26 mm squares = 208 mm, which fits the Bambu Lab
P1S's 256 mm plate while leaving room for the multi-color purge tower (single
nozzle = every color change purges). The board is built from OpenCV's own
CharucoBoard render, so it matches the detector exactly — configure your
detector with the same parameters printed to the console (squares, square mm,
marker mm, dictionary). Same flush two-color flat print: filament 1 black,
filament 2 white, flip face-down to print.
| flag | default | meaning |
|---|---|---|
--squares-x / --squares-y |
8 |
board columns / rows |
--square-mm |
26 |
chessboard square side in mm |
--marker-ratio |
0.75 |
marker side as a fraction of the square |
The dictionary must hold at least squares_x * squares_y / 2 markers (it errors
if not — 4x4_50 covers up to a 10×10 board; use 5x5_100/6x6_250 for more).
- Open the
.3mf. It loads as one object with two parts (black→ filament 1,white→ filament 2). Load black in AMS slot 1 and white in slot 2, or remap the two slots in the slicer — that's the only filament setup. - The marker is laid out to match
*_preview.png(not mirrored). Flip the part over in the slicer so the marker face is against the plate, and print face down on a textured PEI plate. The marker face comes off the plate dead-flat, matte, and glare-free — flatness keeps the pose estimate honest, and matte kills the specular hotspots that wreck detection under lights. - PLA is fine. Use a matte black for the best contrast/least glare. Default 0.2 mm layers; the 0.6 mm face is fully opaque over the white backing.
- No supports, no raft. A brim is optional for the thin large slab.
ArUco detection needs a light border around the black border to segment the
marker; without it the marker won't be found regardless of its bits. The label
prints its own white quiet ring (--quiet-cells) so it detects reliably no
matter what it's mounted on.
4x4_50is the default on purpose: fewest bits → largest cells → most robust to motion blur and oblique viewing angles while your head moves on camera.- Use several distinct ids around the band (front, both temples, top) so at least one marker is always cleanly visible across the rotation range.
- Keep the printed labels flat and rigidly mounted; measure the marker edge length you actually printed (footprint minus quiet zone) and feed that to your pose solver as the real-world marker size.
arucogen's source is MIT. Marker/board patterns are generated at
runtime by OpenCV (cv2.aruco, Apache-2.0) — no third-party code or dictionary
tables are vendored here. Dependencies (OpenCV, NumPy, Python) are installed
separately via pixi and documented in THIRD_PARTY.md.
Files you generate (.3mf, .png) are not covered by the MIT license and may
be used without restriction, except where they incorporate third-party or
user-supplied content.
