The Problem

Deploying an Automatic License Plate Recognition (ALPR) service often requires stitching together a detector, an OCR engine, and runtime glue code. Teams spend time writing boiler‑plate wrappers, handling model loading, and exposing a clean API. Fast‑ALPR supplies a ready‑made Python package that hides those details behind a single ALPR class.

What This Does

The repository implements a thin, extensible wrapper around ONNX‑based detection and OCR models. Core logic lives in fast_alpr/alpr.py, which defines the public ALPR class and its predict method. Model defaults are provided by fast_alpr/default_detector.py (DefaultDetector) and fast_alpr/default_ocr.py (DefaultOCR). Shared data structures such as BoundingBox, DetectionResult, and OcrResult are defined in fast_alpr/base.py. Tests in test/test_alpr.py exercise the end‑to‑end flow.

How It Is Wired

Execution starts when a client instantiates fast_alpr.ALPR (file fast_alpr/alpr.py).

  1. fast_alpr/alpr.py – __init__ * Imports and constructs DefaultDetector and DefaultOCR (calls __init__ in fast_alpr/default_detector.py and fast_alpr/default_ocr.py).
  1. fast_alpr/alpr.py – predict Calls self.detector.predict → fast_alpr/default_detector.py → BaseDetector.predict (from fast_alpr/base.py). The detector returns a DetectionResult containing plate bounding boxes.
  1. fast_alpr/alpr.py – predict (continued) For each detection, calls self.ocr.predict → fast_alpr/default_ocr.py → BaseOCR.predict (also in fast_alpr/base.py). OCR returns an OcrResult with the recognized string.
  1. Result Assembly * predict builds an ALPRResult (defined in fast_alpr/alpr.py) that aggregates detection and OCR data.
  1. Optional Visualization * draw_predictions (in fast_alpr/alpr.py) accepts an image and an ALPRResult, then calls draw_predictions → predict (internal edge) to overlay bounding boxes.

The internal call graph shows 11 resolved edges. The most widely used functions are predict (called from both the test fixture and the public API) and ALPR (the class constructor). No circular imports are present, and the module with the highest inbound degree is fast_alpr/base.py (four other modules import its types).

How To Use It

# Clone the repo
git clone https://github.com/moses-y/fast-alpr
cd fast-alpr

# Install with ONNX runtime (CPU example)
pip install "fast-alpr[onnx]"

# Run the library in a Python REPL or script
python - <<'PY'
from fast_alpr import ALPR

alpr = ALPR(
    detector_model="yolo-v9-t-384-license-plate-end2end",
    ocr_model="cct-xs-v1-global-model",
)

# assets/test_image.png is shipped with the repo
result = alpr.predict("assets/test_image.png")
print(result)
PY

The package does not ship a CLI script; the entry point is the ALPR class in fast_alpr/alpr.py. No additional configuration files or environment variables are required for the default models. If custom models are used, they must be supplied as arguments to ALPR.

Real‑World Use

A parking‑lot management system can instantiate ALPR at service start‑up, keep the detector and OCR objects in memory, and call alpr.predict(frame) for each captured camera frame. The returned ALPRResult supplies the plate string and its location, which can be logged to a database or passed to an access‑control API.

Code Health & Issues

  • High – Pin third‑party GitHub Actions – .github/workflows/*.yaml uses tags (@v6, @v1). Replace with commit SHA to avoid supply‑chain risk.
  • Medium – Declare least‑privilege GITHUB_TOKEN permissions – ci.yaml lacks a permissions: block; add contents: read (and narrow per job).
  • Medium – Enable Dependabot or Renovate – No update bot configured despite a pyproject.toml. Add .github/dependabot.yml.
  • Medium – Add dependency‑vulnerability scan – No scan step in CI; integrate dependency-review-action or osv-scanner.
  • Low – Set timeout-minutes on workflow jobs – Jobs in ci.yaml have no timeout; specify a reasonable limit (e.g., timeout-minutes: 30).

Additional observations: the repo includes a LICENSE, a full test suite (test/test_alpr.py), and CI via GitHub Actions, but it lacks a lockfile for reproducible builds (no uv.lock is committed). The existing uv.lock file is present but not referenced in the CI configuration.

The Bottom Line

Fast‑ALPR delivers a compact, well‑documented Python wrapper that lets developers plug in ONNX detection and OCR models with a single ALPR object. The codebase is small and test‑covered, but production use should address the high‑severity CI security gaps and add a lockfile for deterministic installs. Suitable for teams that need a quick, extensible ALPR component without building the model‑pipeline from scratch.