--- 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.