The Collectable Card Identifier project identifies individual trading cards from photographs. It starts with the Pokémon TCG and is built to take Magic: The Gathering and Yu-Gi-Oh! later. It has two parts:
- Dataset manager. It fetches card data and one scan per card, then generates many randomized training images per card, and selects any subset of cards for a dataset (a set, a series, only the cards legal in Standard).
- Identifier. It trains models on a selected dataset, evaluates them on real photos, and identifies cards and their labels. More than one architecture is trainable.
The first consumer is a card sorting robot. Inventory and valuation tools follow.
The dataset manager exists today and has known defects. The identifier is planned. Start with docs/intent.md for the purpose, docs/specs/ for the requirements, and the GitHub issues for the backlog. docs/README.md explains how intent, specs, decisions and issues fit together.
This project uses uv to manage dependencies and requires Python 3.13 or newer. After cloning the repository, install the project and its development tools:
uv syncThis creates .venv, installs the locked runtime and dev dependencies, and
makes the mkdataset command available through uv run.
Enable the git hook with prek so ruff, pyright and pytest run before each commit:
uv run prek installThe optional Streamlit demo in scripts/streamlit needs its own dependency
group: uv sync --group streamlit.
Helper tasks (container builds, model training) run with
go-task. task --list shows them.
Several environment variables control where datasets and images are stored. They all default to sub-directories of data if not set.
| Variable | Description | Default |
|---|---|---|
CARDIDENT_DATA_ROOT |
Root directory for all data assets. | data |
CARDIDENT_BACKGROUNDS_DIR |
Location of background images. | $CARDIDENT_DATA_ROOT/backgrounds |
CARDIDENT_IMAGES_DIR |
Where original card images are downloaded. | $CARDIDENT_DATA_ROOT/images/originals |
CARDIDENT_DATASETS_DIR |
Destination for generated dataset images. | $CARDIDENT_DATA_ROOT/images/dataset |
CARDIDENT_DEBUG |
Enable debug logging across multiprocessing workers. | 0 |
First ensure card images are downloaded. For Pokémon cards this can be done with:
uv run mkdataset card-data -t pokemon --imagesGenerate a dataset of 500 images:
uv run mkdataset create-dataset -t pokemon -n 500All data lives beneath CARDIDENT_DATA_ROOT (defaults to data).
Important subdirectories are:
$CARDIDENT_DATA_ROOT/
backgrounds/ # background images used for dataset generation
barrel/<game>/ # pickled state files and RNG snapshots
images/
originals/<game>/ # downloaded card scans
dataset/<game>/ # generated dataset images
Generated datasets are stored by set and card ID. For example:
$CARDIDENT_DATA_ROOT/images/dataset/pokemon/<set>/<card-id>/*.png
Training symlinks produced by DatasetManager.mk_symlinks are placed in
dataset/<game>/symlinks/<mode> where <mode> is all, legal, or sets.
A typical workflow is:
-
Download card metadata and images:
uv run mkdataset card-data -t pokemon --refresh --images
-
Generate randomized dataset images (populate
CARDIDENT_BACKGROUNDS_DIRwith background images first):uv run mkdataset create-dataset -t pokemon -n 500
-
Trim each card directory to the desired size:
uv run mkdataset trim-dataset -t pokemon -n 200
-
Create symlink trees for training:
from card_identifier.dataset import DatasetManager dm = DatasetManager("pokemon") dm.mk_symlinks("all") # or 'legal'/'sets'
Set CARDIDENT_DEBUG=1 to enable debug messages from all worker processes. The
--debug flag in the CLI sets this variable automatically.
uv sync installs the test dependencies. Run the test suite before committing
changes:
uv run pytest -n autoRun every check (formatting, lint, type check and tests) at once with:
uv run prek run --all-filesEach check also runs on its own:
uv run ruff check .
uv run ruff format --check .
uv run pyrightpyright reads its settings from
[tool.pyright] in pyproject.toml and finds packages in .venv, so editors
and language servers that run pyright-langserver from the repository root
need no extra setup after uv sync.
The code is AGPL-3.0-or-later. Card images belong to their owners. This project downloads them for local training, keeps them out of git and out of container images, and does not redistribute them. Pretrained model weights carry their own licences, and some forbid commercial use. See docs/intent.md for the constraints.