Instructions to use sroot/lgd-cards-gen4 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- ultralytics
How to use sroot/lgd-cards-gen4 with ultralytics:
from ultralytics import YOLOvv11 model = YOLOvv11.from_pretrained("sroot/lgd-cards-gen4") source = 'http://images.cocodataset.org/val2017/000000039769.jpg' model.predict(source=source, save=True) - Notebooks
- Google Colab
- Kaggle
lgd-cards-gen4 β playing-card corner-pip detector (spread-recall fine-tune)
4th-generation card detector for Live Game Defender, an on-prem
computer-vision integrity monitor for live casino table games. Detects the 52 rank+suit corner
index pips (AS, 10H, KD, β¦) on an overhead table camera β one card shows up to two pip
boxes; whole-card assembly happens downstream in the tracker, not here.
License / provenance. AGPL-3.0. This is a fine-tune of Ultralytics YOLO11s (COCO pre-trained), so the weights are a YOLO derivative β not "ours". Downstream use inherits AGPL.
β οΈ Not casino accuracy. All numbers below are on our own PoC / Czech Croupier Academy footage with LLM-verified labels, not human casino ground truth. Treat as PoC metrics only.
Status: spread specialist β NOT the production model
gen4 was activated on 2026-07-20 and reverted the same day: its gameplay-precision trade broke
the ante-integrity pillar on gameplay footage. Two measured issues (KAS-35 E2E,
uth_player3_ante_paid.mp4): (a) hot nested double-reads β it read a 7H pip's bare rank digit
as "7C" at 73% confidence, minting a phantom board pair that faked "dealer qualifies"; (b) it
missed two players' hole cards outright. lgd-cards-gen3
is the production/served model. gen4 remains the best deck-spread specialist (45/52 live deck
check vs fewer under gen3); the planned gen5 warm-starts from gen3's weights + this model's spread
data and must beat both the spread gate and the gameplay E2E.
Why gen4
gen4 targets the one thing prior gens were weak at: recall on a fully spread deck (the dealer
fanning all 52 cards face-up β the KAS-52 "cards missing / only 1 card" report, and the input to the
KAS-36 deck-completeness check). It is the same recipe as gen3 with one added dataset: day-3
deck-spread video (lgd-cards-video-day3).
Metrics (frozen held-out real video, eval_real.py, serve-style 6Γ4 tiling @ 4K, threshold 50)
Scored against the previous served model (gen3 = day-2) in one run, both on the same expanded 318-frame holdout (225 prior frames + 93 newly-held-out deck-spread frames β never trained on):
| Recall (cards found) | Precision-proxy | |
|---|---|---|
| gen4 (this model) | 0.786 | 0.752 |
| gen3 (day-2, prior served) | 0.750 | 0.774 |
On the 93 deck-spread-only frames β the target scenario:
| Recall | count-of-52 unique codes (mean) | best frame | |
|---|---|---|---|
| gen4 | 0.665 | 26.2 / 52 | 32 / 52 |
| gen3 | 0.574 | 23.0 / 52 | 24 / 52 |
+9 points of spread recall. Normal-gameplay recall is held (~0.848 β 0.853). gen4 does not
reach a full 52, and its precision-proxy dips β partly a genuine trade (it detects more
aggressively) and partly an artifact: the LLM-made holdout GT is not exhaustive, so real cards gen4
recovers that the GT lacks score as false positives. It fails the strict "beat the previous model
on both axes" gate; it was activated for the recall win on 2026-07-20 and reverted the same
day (see Status above). Full numbers in metrics.json.
Numbering note: gen3's headline figure elsewhere (0.85) was on an older 225-frame holdout; on the same 318-frame holdout used here gen3 scores 0.750, which is the fair comparison. Naming was unified 2026-07-20:
genNmeans the same model on HF, in the project'sgenerations/genN-*archive (this one:generations/gen4-spread) and in every doc.
Files
model.onnxβ deployable ONNX (dynamic batch) β the exact export served during its brief 2026-07-20 activation (not currently deployed; see Status).model.classes.jsonβ the 52 class names, in model output order.best.ptβ Ultralytics checkpoint (for resuming / re-export).metrics.jsonβ full eval incl. per-label recall and the reference-model comparison.
Usage (onnxruntime, no Ultralytics at runtime)
import onnxruntime as ort, numpy as np, json
sess = ort.InferenceSession("model.onnx", providers=["CUDAExecutionProvider", "CPUExecutionProvider"])
names = json.load(open("model.classes.json"))
# letterbox your BGR frame to 640Γ640, NCHW float32 /255; run sess.run(None, {input: x});
# decode YOLO11 output [1,56,8400] -> boxes+52 class scores, NMS. For 4K, tile (serve uses 6Γ4).
The engine runs this tiled (full frame + a 6Γ4 overlap grid at 4K) at a confidence threshold of 50.
Training
YOLO11s (COCO) β fine-tuned 40 epochs (patience 15, batch 16, imgsz 640, seed 7) on the Roboflow
ow27d base set (oversampled, not redistributed here β get it from
Roboflow Universe) mixed with
lgd-cards-video-day1 + -day2 + -day3 (the new deck-spread tiles). Labels are
detector-proposed, OpenAI-gpt-5-mini-verified against the closed 52-code vocabulary.
Family
Cards: gen1 Β· gen2 Β· gen3 Β· gen4 (this) Β· Chips: gen1 Β· gen2
- Downloads last month
- 2