""" License plate OCR using EasyOCR. Accepts a cropped plate image (numpy array) and returns extracted text. """ import re import numpy as np import easyocr # Singleton reader to avoid reloading the model on every call _reader = None def get_reader() -> easyocr.Reader: global _reader if _reader is None: _reader = easyocr.Reader(["en"], gpu=False, verbose=False) print("[OCR] EasyOCR reader initialised") return _reader def read_plate(crop: np.ndarray) -> str: """ Extract license plate text from a BGR/RGB crop. Returns: Cleaned plate string (e.g. "KA05MN1234") or "" if nothing detected. """ if crop is None or crop.size == 0: return "" reader = get_reader() results = reader.readtext(crop, detail=1, paragraph=False) if not results: return "" # Pick the result with highest confidence best = max(results, key=lambda r: r[2]) raw_text = best[1] return _clean_plate(raw_text) def _clean_plate(text: str) -> str: """ Normalise OCR output to uppercase alphanumeric only. Common OCR confusions corrected: O↔0, I↔1, S↔5. """ text = text.upper().strip() text = re.sub(r"[^A-Z0-9]", "", text) return text