render-tag SOTA refresh — OpenCV 5.0 (2026-07-13)
Refreshes the detector-comparison matrix after the OpenCV 4.13 → 5.0.0 bump,
with the OpenCV baseline re-tuned for its best 5.0 config. Supersedes the
render_tag_sota_20260425.md snapshot for the OpenCV rows.
2026-07-19 update (v0.7.0). The
Locus (high_accuracy)rows in §1/§2 are refreshed to the v0.7.0 shipped config, which enables model-edge pose refinement by default (pose.pose_edge_refinement_enabled = true). Re-measured on the same AMD EPYC-Milan hardware withrender_tag_sota_eval.py; the competitor rows reproduced bit-for-bit (accuracy is deterministic) and are unchanged. The pre-refinementhigh_accuracybaseline was rot p99 0.600° (1080p) / 1.113° (2160p) at 13.8 / 56.4 ms. Seemodel_edge_refinement_20260715.md.
Methodology
- Datasets:
locus_v1_tag36h11_1920x1080and_3840x2160Hub render-tag subsets (50 scenes, single tag36h11 each); captured viatools/bench/render_tag_sota_eval.py(setRENDER_TAG_SOTA_CONFIGfor 2160p). - Single-threaded latency. Every detector is pinned to one thread for an
apples-to-apples comparison:
cv2.setNumThreads(1), Locusthreads=1, AprilTagnthreads=1,RAYON_NUM_THREADS=1. Latency is the mean per-frame detector-only wall time, measured serially on a quiescent machine. - Hardware (verified,
lscpu): AMD EPYC-Milan, 8 vCPU (4 cores × 2 threads), KVM. Release build (maturin develop --release). Locusgit e3fa5f0. - Versions: OpenCV
cv25.0.0,pupil_apriltags(AprilTag-C). - OpenCV tuning:
bench tune/bench sweepovertools/bench/tune/spaces/opencv_default.json(+ a subpix-refinement extension), n≈32–48 random,precision_floor=0.98.
Accuracy is deterministic (independent of machine load); latency is not, hence the single-thread quiescent protocol.
Two OpenCV operating points
OpenCV's corner-refinement choice is a genuine speed/accuracy lever, so both are reported:
subpix— fast; intensity-gradient corner refinement. Tuned detection thresholds (not the refinement convergence knobs, which don't help) take it from the pre-tuning 141 mm → 66.6 mm trans p99 at the same speed.apriltag— best accuracy; tag-homography-aware refinement. 55.3 mm trans p99 / best rotation tail, at ~2× the subpix latency (1080p). The shippedOpenCVWrapper._DEFAULTS. Note: its refinement rejects markers whose local re-detection fails, so it is best only on clean imagery — see ICRA below.
§1 Detector matrix — 1920×1080 (50 scenes, single thread)
| Detector | Recall | Prec | Trans p50 | Trans p99 | Rot p50 | Rot p99 | Latency |
|---|---|---|---|---|---|---|---|
Locus (high_accuracy) |
100 % | 100 % | 0.4 mm | 20.1 mm | 0.041° | 0.249° | 15.2 ms |
Locus (standard) |
100 % | 100 % | 3.5 mm | 50.3 mm | 0.288° | 27.248° | 32.7 ms |
OpenCV (subpix) |
100 % | 100 % | 3.5 mm | 66.6 mm | 0.127° | 0.569° | 101.1 ms |
OpenCV (apriltag) |
100 % | 100 % | 3.0 mm | 55.3 mm | 0.067° | 0.376° | 195.8 ms |
| AprilTag-C (pupil) | 100 % | 100 % | 2.9 mm | 54.4 mm | 0.061° | 65.365° | 78.5 ms |
Locus high_accuracy wins the translation tail, the rotation tail (0.249° p99,
below OpenCV apriltag's 0.376° — the model-edge refinement shipped on in v0.7.0
closes the gap), and speed (13× faster than OpenCV apriltag).
AprilTag-C's rotation p99 explodes to 65° on symmetric-tag IRLS branch ambiguity.
§2 Detector matrix — 3840×2160 (50 scenes, single thread)
| Detector | Recall | Prec | Trans p50 | Trans p99 | Rot p50 | Rot p99 | Latency |
|---|---|---|---|---|---|---|---|
Locus (high_accuracy) |
100 % | 100 % | 0.8 mm | 37.0 mm | 0.041° | 0.267° | 58.0 ms |
Locus (standard) |
100 % | 100 % | 6.9 mm | 120.8 mm | 0.302° | 108.409° | 125.4 ms |
OpenCV (subpix) |
100 % | 100 % | 6.5 mm | 133.8 mm | 0.104° | 0.489° | 253.9 ms |
OpenCV (apriltag) |
100 % | 100 % | 5.8 mm | 107.5 mm | 0.072° | 0.449° | 885.9 ms |
| AprilTag-C (pupil) | 100 % | 100 % | 5.7 mm | 101.3 mm | 0.072° | 65.716° | 327.2 ms |
At 4K the OpenCV apriltag refinement cost scales badly (886 ms single-thread).
§3 ICRA 2020 Forward (recall + corner RMSE)
ICRA's small / distant / lower-fidelity tags invert the render-tag result:
OpenCV apriltag refinement rejects marginal detections, so it is not
recall-best here. Per-dataset OpenCV sweep (recall × refinement):
| OpenCV config (5.0) | Recall | Corner RMSE |
|---|---|---|
subpix (recall-best, perim 0.005) |
52.6 % | 0.979 px |
apriltag (RMSE-best) |
29.95 % | 0.388 px |
vs the previous OpenCV-4.13 baseline (33.2 % / 0.92 px). The README ICRA row
reports the recall-best subpix config (ICRA is a detection-rate benchmark);
apriltag refinement more than halves corner RMSE but at 30 % recall.
Tuned OpenCV configs
- render-tag
apriltag(OpenCVWrapper._DEFAULTS):cornerRefinementMethod=apriltag,cornerRefinementWinSize=5,adaptiveThreshConstant≈9.76,adaptiveThreshWinSize=[5,30] step 6,minMarkerPerimeterRate≈0.022,minMarkerDistanceRate≈0.041,polygonalApproxAccuracyRate≈0.029. - render-tag
subpix(OpenCVWrapper._SUBPIX_ALT):cornerRefinementMethod=subpix,cornerRefinementWinSize=9,adaptiveThreshConstant=10,adaptiveThreshWinSize=[4,33] step 9,minMarkerPerimeterRate=0.019,minMarkerDistanceRate=0.028,polygonalApproxAccuracyRate=0.023. - ICRA
subpix: as above butminMarkerPerimeterRate=0.005,adaptiveThreshConstant=7.