Skip to content

2160p render_tag_hub recall lift (2026-04-25)

PR #200 shipped render_tag_hub at 100% recall for 480p/720p/1080p, but 2160p stalled at 47/50 (94%). The PR blamed segmentation fragmentation ("pre-EdLines — out of scope"). That diagnosis was wrong.

Root cause

DetectionBatch's MAX_CANDIDATES = 1024 ceiling. At 2160p, EdLines's more-permissive gates accept more candidate quads than ContourRdp, and the total exceeds 1024 on tag-bearing scenes. extract_quads_soa collected components in raster order and truncated with .take(MAX_CANDIDATES); tags in the mid/lower image region (higher label indices) got silently dropped when noise components filled the first 1024 slots. Confirmed via diagnose_render_tag_2160p.rs: the largest CCL component on every failing scene covered ≥90% of GT bbox and passed all geometric gates — segmentation was never the bottleneck, the candidates were produced and then discarded pre-decode.

Ruled out before finding this: iterate-until-converged threshold propagation (fixed fill ratio, zero recall delta), larger tile size (same), opt-in 2× decimation (rescued one scene, collapsed the other 49 by shrinking tags below EdLines' viable size — reverted).

Fix

pixel_count_descending_order(arena, stats) in quad.rs returns the top-MAX_CANDIDATES (pixel_count, label_idx) pairs descending, so truncation drops the smallest blobs (noise) instead of the largest (tag candidates). Bump-allocated (no system-allocator touch in the hot path); select_nth_unstable_by partitions in O(n) before sorting only the surviving prefix; (pixel_count, label_idx) pairs are packed inline for cache-resident comparisons. Applies globally — both the rectified and distortion-aware extraction paths, all profiles, not just render_tag_hub.

Result

2160p render_tag_hub: 47/50 → 50/50, precision held at 1.000 (r p90 rose 0.416° due to scene 0033's fill=0.14 grazing-angle render joining the population, not a regression). high_accuracy (same root cause) also lifted 47/50 → 50/50. Full-suite sweep: every snapshot delta was strictly an improvement (recall up, precision unchanged/up) across render_tag (2 rebound), render_tag_robustness (2 rebound, tag16h5 precision +3.5pp), distortion_hub Brown-Conrady (1 rebound, recall +0.6pp) — board_hub, ICRA, Kannala-Brandt unchanged. No JSON profile, schema, or Python binding touched; ~5 lines of Rust.

At 2160p Locus (high_accuracy) matches AprilTag-C on recall+precision and leads on latency (73ms vs 143/165ms), trailing OpenCV's tighter rotation distribution — the same EdLines grazing-angle pose-ambiguity effect discussed in render_tag_sota_20260425.md §1.