Instructions to use HanClinto/cornelius with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- CollectorVision
How to use HanClinto/cornelius with CollectorVision:
pip install git+https://github.com/HanClinto/CollectorVision huggingface_hub
from huggingface_hub import hf_hub_download import collector_vision as cvg checkpoint = hf_hub_download(repo_id="HanClinto/cornelius", filename="model.onnx") # Detector models, such as Cornelius: detector = cvg.NeuralCornerDetector(checkpoint) # Embedder models, such as Milo: embedder = cvg.NeuralEmbedder(checkpoint)
- Notebooks
- Google Colab
- Kaggle
| license: agpl-3.0 | |
| library_name: collectorvision | |
| tags: | |
| - onnx | |
| - object-detection | |
| - card-detection | |
| - mobilevit | |
| base_model: apple/mobilevit-xx-small | |
| # Cornelius — CCG Card Corner Detector | |
| MobileViT-XXS corner detector trained to locate the four corners of a CCG card | |
| (Magic: The Gathering, Pokémon, etc.) in a photograph or video frame. | |
| ## Model details | |
| | Property | Value | | |
| |---|---| | |
| | Architecture | MobileViT-XXS + global-token SimCC head | | |
| | Input | 384×384 RGB, ImageNet-normalised | | |
| | Outputs | corners (8 floats, normalised [0,1]), compatibility presence logit, sharpness scalar | | |
| | Parameters | ~1.06M | | |
| | File size | 4.2 MB (fp32 ONNX, simplified) | | |
| | Local CPU speed | 23.2 ms / frame, 43.0 FPS (ONNX Runtime CPU, single thread, 384×384) | | |
| | Codename | cornelius | | |
| | Latest version | 2.12 | | |
| ## Versions | |
| | File | Notes | | |
| |---|---| | |
| | `cornelius-2.12.onnx` / `model.onnx` | Global-token SimCC production model. Smaller than 1.x (~1.06M params vs ~1.82M) and substantially more robust under rotation/occlusion. Full-rotation stress: mean IoU 0.970411, p10 0.954621, 0 bad, 0 collapse. | | |
| | `cornelius-1.221.onnx` | Fixed SimCC coordinate decoding to use peak argmax instead of soft expectation. This addresses rotated-card failures where multi-modal corner distributions decoded to implausible between-peak coordinates; see [CollectorVision issue #24](https://github.com/HanClinto/CollectorVision/issues/24). | | |
| | `cornelius-1.210.onnx` | Earlier beta-test candidate. Combined held-out IoU 0.8857. | | |
| ## Evaluation | |
| All IoU values are quadrilateral IoU between predicted and labelled card corners. | |
| `bad` counts predictions with IoU `< 0.5`; `collapse` counts geometrically | |
| degenerate predictions where two predicted corners nearly coincide. | |
| ### Release comparison | |
| | Version | Architecture | Params | ONNX size | Normal held-out IoU | Full ±50° rotation mean / p10 | Full-rotation bad / collapse | Notes | | |
| |---|---:|---:|---:|---:|---:|---:|---| | |
| | 2.12 | MobileViT-XXS + global-token SimCC | ~1.06M | 4.2 MB | 0.968911 | 0.970411 / 0.954621 | 0 / 0 | Current default `model.onnx`; selected production checkpoint. | | |
| | 1.221 | MobileViT-XXS + independent SimCC | ~1.82M | 7.1 MB | — | 0.933910 / 0.928732 | 138 / 91 | Strong normal detector, but vulnerable to rotation-induced corner collapse. | | |
| | 1.210 | MobileViT-XXS + independent SimCC | ~1.82M | 7.1 MB | 0.8857 combined | — | — | Earlier beta; reported combined held-out IoU 0.8857. | | |
| ### Cornelius vs fastweb-single | |
| Cornelius remains the stable, conservative default. The `fastweb-single` | |
| family is also available through the stable channel for consumers that explicitly | |
| select it; it is a smaller EfficientViT-B0 global-token SimCC detector being | |
| evaluated as a faster replacement candidate. Both models use the same 384×384 | |
| input contract and produce `corners`, compatibility `presence`, and `sharpness` | |
| outputs. | |
| | Model | Channel | Normal test IoU | Normal collapse | Full ±50° mean / p10 IoU | Full-rotation bad / collapse | ONNX size | Params | Local CPU speed | | |
| |---|---|---:|---:|---:|---:|---:|---:|---:| | |
| | Cornelius 2.12 | stable | **0.968911** | 18 | 0.970411 / 0.954621 | **0 / 0** | 4.41 MB | 1.05M | 23.2 ms / 43.0 FPS | | |
| | fastweb-single 1.39 | stable + testing | 0.968839 | **13** | **0.974255 / 0.960757** | 1 / 0 | **3.19 MB** | **0.77M** | **8.4 ms / 119.4 FPS** | | |
| Takeaways: | |
| - Normal accuracy is effectively tied: fastweb-single trails Cornelius by | |
| 0.000072 IoU on the normal held-out test. | |
| - fastweb-single is about 28% smaller on disk and about 2.8× faster in the | |
| local single-thread CPU benchmark. | |
| - fastweb-single has stronger rotation-stress mean and p10 IoU, but still has | |
| one remaining bad rotation-stress case where Cornelius has zero. | |
| - The current published fastweb-single ONNX uses the same argmax SimCC decoding | |
| style; small post-hoc parabolic peak-refinement gains were observed in local | |
| experiments but are not baked into this artifact. | |
| Speed benchmark details: ONNX Runtime 1.24.4, CPUExecutionProvider, | |
| `intra_op_num_threads=1`, `inter_op_num_threads=1`, 50 warmup runs and 300 timed | |
| runs on a 384×384 float32 input. These numbers are intended for model-to-model | |
| comparison on the same machine, not as universal device benchmarks. | |
| ### Cornelius 2.12 checkpoint selection | |
| The 2.12 release was selected from a low-LR continuation because it best balanced | |
| normal accuracy and stress robustness: | |
| | Checkpoint | Normal test IoU | Normal collapse | Full ±50° mean IoU | p10 IoU | bad | collapse | | |
| |---|---:|---:|---:|---:|---:|---:| | |
| | epoch 9 | 0.968923 | 19 | 0.968892 | 0.952787 | 1 | 0 | | |
| | **epoch 12 / 2.12** | **0.968911** | **18** | **0.970411** | **0.954621** | **0** | **0** | | |
| | epoch 14 | 0.968777 | 18 | 0.968660 | 0.952481 | 0 | 0 | | |
| ### Occlusion + rotation smoke test | |
| Three hand-picked occlusion stress samples were swept through the same full | |
| rotation preset. The 2.12 numbers below are from the Hugging Face-downloaded | |
| `model.onnx`. | |
| | Model | Mean IoU | p10 IoU | bad | collapse | | |
| |---|---:|---:|---:|---:| | |
| | Cornelius 2.12 | 0.888789 | 0.795696 | 0 | 0 | | |
| | Frozen global-token prototype | 0.772039 | 0.673141 | 0 | 0 | | |
| | Hydra4 reduce4_h64 prototype | 0.736071 | 0.648447 | 0 | 0 | | |
| | Cornelius 1.x baseline | 0.687937 | 0.406498 | 22 | 21 | | |
| Per-sample Cornelius 2.12 results: | |
| | Sample | Mean IoU | p10 IoU | min IoU | bad | collapse | | |
| |---|---:|---:|---:|---:|---:| | |
| | Ingenious Skaab | 0.963076 | 0.951756 | 0.939898 | 0 | 0 | | |
| | LTR 566 | 0.883024 | 0.847024 | 0.836244 | 0 | 0 | | |
| | Wall of Fire | 0.820269 | 0.779252 | 0.763541 | 0 | 0 | | |
| ## Outputs | |
| - **corners** — 8 floats `[x0,y0, x1,y1, x2,y2, x3,y3]` in TL→TR→BR→BL order, normalised [0,1] | |
| - **presence** — compatibility logit. For 2.x this is a constant `1.0`; prefer the sharpness gate. | |
| - **sharpness** — mean peak of the 8 SimCC softmax distributions; use this for card-present gating. | |
| ## Usage | |
| The easiest way to use Cornelius is through the [CollectorVision](https://github.com/HanClinto/CollectorVision) library, which wires it into a full detect → dewarp → embed → identify pipeline: | |
| ```python | |
| import collector_vision as cvg | |
| cvid = cvg.Identifier(cvg.HFD("HanClinto/milo", "scryfall-mtg")) | |
| result = cvid.identify("photo.jpg") | |
| print(result.ids) # {"scryfall_id": "..."} | |
| ``` | |
| ### Direct ONNX usage | |
| ```python | |
| import onnxruntime as ort | |
| import numpy as np | |
| from PIL import Image | |
| session = ort.InferenceSession("model.onnx") | |
| # Preprocess: resize to 384×384, ImageNet normalise, NCHW float32 | |
| img = Image.open("photo.jpg").convert("RGB").resize((384, 384)) | |
| x = np.array(img, dtype=np.float32) / 255.0 | |
| x = (x - [0.485, 0.456, 0.406]) / [0.229, 0.224, 0.225] | |
| x = x.transpose(2, 0, 1)[None] # (1, 3, 384, 384) | |
| corners, presence, sharpness = session.run(None, {"image": x}) | |
| # corners: (1, 8) — x0,y0,x1,y1,x2,y2,x3,y3 normalised [0,1], TL→TR→BR→BL | |
| # presence: (1,) — compatibility logit; use sharpness instead for gating | |
| # sharpness: (1,) — mean peak of the 8 SimCC softmax distributions | |
| if sharpness[0] > 0.02: | |
| pts = corners[0].reshape(4, 2) | |
| ``` | |
| ## Part of CollectorVision | |
| Used together with [HanClinto/milo](https://huggingface.co/HanClinto/milo) in the [CollectorVision](https://github.com/HanClinto/CollectorVision) inference library. | |