CV ArUco Detect Markers
ArUco detection in one node — and the one setting that makes it return nothing
- image
- corners
- ids
- count
This is the entry point to every fiducial workflow in this pack: give it a photo or frame, get back the four corners of each marker and its integer ID. From there you either draw them for a sanity check (CV ArUco Draw Markers) or solve the board's 3D pose (CV ArUco Board Pose (Average)) for an AR overlay, a camera track, or a homography that lets you warp one repaired frame onto the rest of a clip.
It's a thin wrapper around cv2.aruco.ArucoDetector - a class, which is why it exists as a curated node rather than one of the pack's ~470 auto-generated raw cv2.* wrappers (the generator only sees top-level functions).
The dictionary is the whole game
dictionary must match the family the printed markers came from. Get this wrong and detection doesn't degrade - it returns zero markers, forever, with no error. DICT_6X6_250 is the default and a sane one; the NxN is the marker's internal bit grid (more bits = more robust ID space, slightly fussier printing) and the trailing number is how many distinct IDs exist. If you generated your board with CV ArUco Board Image, just use the same dictionary there and here. The dropdown is built from whatever cv2.aruco your OpenCV build actually exposes, so a build without contrib support shows you an explicit "not available" entry instead of an empty menu.
image takes a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY, BGR or gray.
Outputs
corners- (N, 4, 2) float32, clockwise from top-left. Empty(0, 4, 2)when nothing was found.ids- (N,) int32.count- how many markers.
Finding nothing is a valid result, not an error. That's a deliberate convention across this pack's detectors and it's the right one: a clip where the board leaves frame for twenty frames should keep running, not die mid-batch. Branch on count (or a truthiness check) rather than assuming there's something there. The empty arrays are typed correctly, so downstream nodes won't blow up on them either.
Install
Manager → ComfyUI CV, or:
cd ComfyUI/custom_nodes && git clone https://github.com/bmad4ever/comfyui_cv
pip install "opencv-contrib-python-headless~=5.0.0.93"
Requires Python ≥ 3.12 and a current ComfyUI on the V3 node API. If ArUco nodes disappear after you installed some other vision pack, check which OpenCV wheel won: all four distributions share one site-packages/cv2, and a later non-contrib wheel empties the contrib submodules. tools/repair_opencv_contrib.py --check in the pack folder will tell you.
Where people get burned
- Wrong dictionary - silent zero detections. If a marker you can see with your eyes isn't found, this is the first thing to check, before you start blaming blur.
- Print quality and quiet zones. Markers need a white border; a marker cropped flush to the paper edge or printed on a glossy sheet that blows out under your lighting is often missed.
- Batch behaviour. An IMAGE batch is treated as one frame (frame 0). If you want per-frame detection across a video you loop - the pack's per-frame nodes plus an Inspire-style foreach is the usual shape - and detection cost is small enough that people do run it per frame.
- Angles. ArUco is happy with oblique views, but severe perspective plus motion blur costs you the smaller markers first. Shoot flat-ish, keep the board big in frame, and it just works.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | NPARRAY,IMAGE | Image containing the markers (BGR or gray). Accepts a ComfyUI IMAGE/MASK directly (frame 0 of a batch) or an NPARRAY. Arithmetic ops (add, multiply, etc.) process the full IMAGE batch when both inputs have the same batch size. | |
| dictionary | COMBO | DICT_6X6_250 | ArUco dictionary the markers belong to. The NxN in the name is the marker's internal bit grid; the trailing number is the dictionary size. Must match the printed markers. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| corners | NPARRAY | Marker corners, (N, 4, 2) float32 in clockwise order starting top-left. Empty (0, 4, 2) when none found. |
| ids | NPARRAY | Marker ids, (N,) int32. Empty (0,) when none found. |
| count | INT | Number of markers detected. |