Skip to content

Repository files navigation

Wheels Model

Recognize a vehicle's make, model, and (where possible) year from a photo. The founding idea was to treat the wheel/rim as a fingerprint; the research pass (docs/architecture.md) tested that premise and reframed it honestly:

  • Whole-car make/model/year is near-solved (~95% top-1 on Stanford Cars with a plain CNN) — the signal lives in body outline, greenhouse/window shape, and proportions.
  • The wheel is a strong-but-fallible fine-grained cue, not a fingerprint. One OEM design is shared across many models/years; one model-year ships several wheels; aftermarket/replica wheels sever the link entirely and cause confident false positives.

So the system is a whole-car classifier with the wheel as an optional tie-breaker for cases the body can't separate (badge-engineered platform twins) — matching the "sieve an image through several models" framing, with the body carrying the load and the wheel adding fine-grained lift only where it measurably helps.

The pipeline

photo ─▶ whole-car make/model/year classifier  (the body baseline — carries ~95%)
   │
   └─▶ detect wheel(s) ─▶ crop ─▶ embed (metric-learning encoder)
                                    │
                                    ▼
                        nearest-neighbor over wheel design index
                                    │
        late-fusion re-rank with body outline / size / window shape / color
        + fitment-DB plausibility + abstention on aftermarket / unknown
                                    ▼
              ranked (make, model, year-range) candidates + confidence

The wheel path uses an embedding + nearest-neighbor design (not a fixed closed-set classifier) so the label space can grow every model year, new designs enroll few-shot, and the output degrades gracefully to a ranked top-k with an explicit "unknown".

Feasibility, up front

  • Wheel-only exact make/model/year is not achievable. The wheel's real contribution is a number we measure — the gap between the ~95% body baseline and wheel-crop-only accuracy — not one borrowed from prior work.
  • Year can't come from the wheel alone (designs persist 10–15 years); at best a generation/range via fusion + a fitment database.
  • The build is therefore gated: two cheap kill-switch experiments (experiments/phase_minus_1) decide whether the wheel branch is worth building at all, before any dataset is assembled.

Roadmap (gated)

Phase Deliverable
−1 Kill-switch gate (1 wk): (a) are wheel designs visually separable across angles? (b) does body+wheel beat body-only? If either fails, stop.
0 Foundations + legality: CVAT + DVC + MLflow, provenance ledger, label-space skeleton, design-id→MMY ground-truth strategy.
1 Body-only baseline (~95% null hypothesis) + first wheel-crop dataset for one make (Toyota) + a wheel detector.
2 Wheel encoder (Sub-center ArcFace) + FAISS index + the decisive ablation (wheel lift over baseline, per class) → go/no-go.
3 Fusion (body/size/greenhouse/color) + abstention + fitment plausibility. Contingent on Phase 2 lift.
4–5 Scale to full make coverage; hardening; commercialization gate (attorney sign-off, permissive-only release).

Full detail, dataset inventory with licenses, and risks: docs/architecture.md.

Repository layout

src/wheels_model/   data (schema), labeling, detect, train, infer, utils   (v0 scaffold)
docs/               architecture.md, sourcing-policy.md
experiments/        phase_minus_1/ — the two kill-switch experiments
config/             config.example.yaml (copy to config.yaml, gitignored)
data/               image corpus (git-ignored; versioned separately)
tests/              schema tests

The target module decomposition (baseline / encode / index / fuse / gate / eval / sourcing) is in architecture.md §10; it's migrated in as each phase lands rather than built empty up front.

Getting started

python -m venv .venv && . .venv/Scripts/activate   # Windows Git Bash
pip install -e ".[dev]"
pytest                                             # schema tests

The ML stack (torch / timm / ultralytics / faiss) installs per-phase; torch is CUDA-specific — see requirements.txt.

Data & labeling

Every image becomes one WheelImage record (schema.py) capturing provenance + license + tier (the legal ledger), the make/model/year target, auxiliary vehicle attributes, the wheel crop box, and wheel attributes including OEM-vs-aftermarket. Images are never committed to git; the corpus is described by a manifest and versioned separately. Sourcing rules: docs/sourcing-policy.md.

About

Infer vehicle make/model/year from a photo, using the wheel/rim as the primary discriminative feature.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages