| --- |
| license: mit |
| library_name: onnx |
| pipeline_tag: image-classification |
| tags: |
| - ocr |
| - persian |
| - farsi |
| - alpr |
| - anpr |
| - license-plate |
| - iran |
| - onnx |
| - computer-vision |
| language: |
| - fa |
| --- |
| |
| # Persian ALPR Models — Iranian License Plates (ONNX) |
|
|
| A complete, portable model bundle for reading **Iranian vehicle license plates**, |
| powering the **Platrix** real‑time ALPR engine. Every model ships as a portable |
| **ONNX** graph, so it runs anywhere [ONNX Runtime](https://onnxruntime.ai/) runs — |
| no TensorFlow or PyTorch required at inference time. |
|
|
| The recommended pipeline is two models: **detect the plate** (YOLO) → **read the |
| whole plate** (CRNN). |
|
|
| - **Author:** [Dibachain](https://huggingface.co/Dibachain) |
|
|
| > **Project & source code:** **https://github.com/AliAkrami1375/Platrix** |
|
|
| --- |
|
|
| ## Files |
|
|
| | File | Description | |
| |------|-------------| |
| | `plate_yolo.onnx` | **Plate detector** — a YOLOv8 model that localizes the plate in a full frame (single "plate" class). | |
| | `ocr_crnn.onnx` | **Whole‑plate reader** *(recommended)* — a CRNN+CTC model that reads the entire plate in one pass (no character segmentation). Input `1×1×32×128` grayscale; output `(T, 33)` logits, CTC‑decoded. Trained on realistic full‑plate images with the official plate font + augmentation. | |
| | `ocr_crnn.labels.json` | Class list for the CRNN (CTC blank is the last index). | |
| | `ocr_cnn.onnx` | **Per‑character classifier** *(alternative)* — a small CNN that classifies a single segmented glyph (`1×1×32×32` → 28 classes). Trained on real plate character crops. | |
| | `ocr_cnn.labels.json` | Class list for the per‑character CNN. | |
|
|
| --- |
|
|
| ## How the pipeline works |
|
|
| 1. **Detect** the plate in the frame with `plate_yolo.onnx`. |
| 2. **Read** the whole plate crop with `ocr_crnn.onnx` (CRNN + CTC) — no character |
| segmentation, so there are no split/merge errors. Output is decoded with a |
| greedy CTC pass into the plate string. |
|
|
| The CRNN is trained on realistic full‑plate images rendered with the **official |
| Iranian plate font and layout**, plus perspective / rotation / motion‑blur / |
| illumination augmentation, so it transfers to real plate crops. |
|
|
| --- |
|
|
| ## Usage — whole‑plate reader (recommended) |
|
|
| ```python |
| import json |
| import numpy as np |
| import cv2 |
| import onnxruntime as ort |
| from huggingface_hub import hf_hub_download |
| |
| onnx = hf_hub_download("Dibachain/ocr-persian", "ocr_crnn.onnx") |
| labels = json.load(open(hf_hub_download("Dibachain/ocr-persian", "ocr_crnn.labels.json"), encoding="utf-8")) |
| blank = len(labels) # CTC blank is the last index |
| |
| sess = ort.InferenceSession(onnx, providers=["CPUExecutionProvider"]) |
| name = sess.get_inputs()[0].name |
| |
| def read_plate(plate_bgr): |
| gray = cv2.cvtColor(plate_bgr, cv2.COLOR_BGR2GRAY) |
| img = cv2.resize(gray, (128, 32)).astype("float32") / 255.0 |
| logits = sess.run(None, {name: img.reshape(1, 1, 32, 128)})[0][0] # (T, C) |
| idx = logits.argmax(1) |
| out, prev = [], -1 |
| for i in idx: |
| if i != blank and i != prev and i < len(labels): |
| out.append(labels[int(i)]) |
| prev = int(i) |
| return "".join(out) # e.g. "81و63813" |
| ``` |
|
|
| ### With Platrix (end‑to‑end) |
|
|
| ```bash |
| git clone https://github.com/AliAkrami1375/Platrix.git |
| cd Platrix && pip install -r requirements.txt |
| huggingface-cli download Dibachain/ocr-persian \ |
| ocr_crnn.onnx ocr_crnn.labels.json plate_yolo.onnx --local-dir models/ |
| platrix serve # auto-uses YOLO + CRNN, dashboard on http://localhost:8080 |
| ``` |
|
|
| --- |
|
|
| ## Labels |
|
|
| - **CRNN** (`ocr_crnn.labels.json`): the digits `0–9` and Persian plate letters |
| (`ا ب پ ت ث ج ح د ز ژ س ص ط ع ق ل م ن و ه ی`). The CTC **blank** is the extra, |
| last index (`len(labels)`). |
| - **Per‑character CNN** (`ocr_cnn.labels.json`): 28 classes, one neuron per glyph. |
|
|
| --- |
|
|
| ## Model architectures |
|
|
| - **CRNN reader:** a 5‑block CNN → 2‑layer bidirectional LSTM → linear, trained |
| with CTC loss. Input `1×1×32×128`. ~96% exact‑plate accuracy on held‑out |
| synthetic plates and strong transfer to real photos. |
| - **Per‑character CNN:** `Conv → Conv → Pool → Conv → Pool → FC → FC`, trained on |
| real plate character crops (~98% validation accuracy). |
|
|
| --- |
|
|
| ## Intended use & limitations |
|
|
| - **Intended for** parking, access control and traffic‑analytics pipelines that |
| first detect and segment plates, then classify each character with this model. |
| - **Not** an end‑to‑end plate reader on its own — it classifies **single, |
| pre‑segmented characters**. Overall accuracy on a full plate depends on the |
| quality of the upstream detection and segmentation. |
| - Real‑world plates vary in font, angle, lighting and wear; for best results, |
| pair with a strong plate detector and clean segmentation. |
|
|
| --- |
|
|
| ## License |
|
|
| Released under the **MIT License**. © Dibachain. |
|
|