--- license: mit library_name: onnx pipeline_tag: image-classification tags: - ocr - persian - farsi - alpr - anpr - license-plate - iran - onnx - computer-vision language: - fa --- # Persian OCR — Character Recognition (ONNX) A compact convolutional neural network that recognizes **Persian license‑plate characters** — the digits `0–9` and the Persian letters used on Iranian vehicle plates. It is the OCR stage of the **Platrix** real‑time ALPR engine and ships as a portable **ONNX** graph, so it runs anywhere [ONNX Runtime](https://onnxruntime.ai/) runs — no TensorFlow or PyTorch required at inference time. - **Task:** single‑character image classification (44 classes) - **Input:** `1 × 1 × 32 × 32` grayscale tensor, values in `[0, 1]` (white glyph on black) - **Output:** `1 × 44` logits → `argmax` → character via the bundled label map - **Format:** ONNX (opset 13), ~2.2 MB - **Author:** [Dibachain](https://huggingface.co/Dibachain) > **Project & source code:** **https://github.com/AliAkrami1375/Platrix** --- ## Files | File | Description | |------|-------------| | `ocr_cnn.onnx` | The inference graph (opset 13) | | `ocr_cnn.labels.json` | Ordered list mapping each output neuron to its character | --- ## How the pipeline works Platrix reads a plate in three stages; this model is stage 3: 1. **Detect** the plate region in the frame. 2. **Segment** the plate into individual character images (normalized to a white‑on‑black `32 × 32` glyph). 3. **Recognize** each glyph with this model and assemble the plate string. The training images are preprocessed **identically** to the segmenter's output (Otsu binarization, tight crop, square‑pad, resize) so the model sees the same glyph framing in training and in production. Training also applies random affine augmentation (scale / shift / rotation) for robustness to how characters are framed. --- ## Usage ```python import json import numpy as np import onnxruntime as ort from huggingface_hub import hf_hub_download onnx_path = hf_hub_download("Dibachain/ocr-persian", "ocr_cnn.onnx") labels_path = hf_hub_download("Dibachain/ocr-persian", "ocr_cnn.labels.json") labels = json.load(open(labels_path, encoding="utf-8")) session = ort.InferenceSession(onnx_path, providers=["CPUExecutionProvider"]) input_name = session.get_inputs()[0].name def classify(glyph_32x32_uint8): """glyph: a 32x32 grayscale image, white character on black background.""" x = (glyph_32x32_uint8.astype("float32") / 255.0).reshape(1, 1, 32, 32) logits = session.run(None, {input_name: x})[0] return labels[int(np.argmax(logits))] ``` ### With Platrix (end‑to‑end plate reading) ```bash git clone https://github.com/AliAkrami1375/Platrix.git cd Platrix pip install -r requirements.txt # place ocr_cnn.onnx + ocr_cnn.labels.json in ./models/ PLATRIX_OCR=onnx platrix serve # dashboard on http://localhost:8080 ``` --- ## Labels 44 classes: the digits `0–9` and the Persian letters. Arabic presentation forms are folded to their base letter (Unicode NFKC) and non‑plate punctuation is removed, so each neuron maps to exactly one plate character. The exact order is in `ocr_cnn.labels.json`. --- ## Model architecture A small CNN: `Conv(32) → Conv(32) → MaxPool → Conv(64) → MaxPool → FC(128) → FC(44)` with dropout, trained with Adam and cross‑entropy. --- ## 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.