""" ocr_reader.py ------------- Wraps EasyOCR so the app can read signs, menus, room numbers, etc. Loaded lazily/cached because EasyOCR's model init is slow (~2-5s) and should only happen once per session, not once per frame. """ from typing import List, Tuple import numpy as np import easyocr class TextReader: def __init__(self, languages: List[str] = None, gpu: bool = False): """ languages: EasyOCR language codes, e.g. ['en'] or ['en', 'fr']. gpu: set True if a CUDA GPU is available -- big speedup for OCR. """ self.languages = languages or ["en"] self.reader = easyocr.Reader(self.languages, gpu=gpu) def read_text(self, frame: np.ndarray, min_confidence: float = 0.4) -> List[Tuple[str, float]]: """ Runs OCR on a single frame. Returns a list of (text, confidence) tuples, left-to-right / top-to-bottom in the order EasyOCR detects them, filtered by min_confidence. """ raw_results = self.reader.readtext(frame) # [(bbox, text, confidence), ...] filtered = [] for _, text, confidence in raw_results: cleaned = text.strip() if cleaned and confidence >= min_confidence: filtered.append((cleaned, confidence)) return filtered def read_text_as_sentence(self, frame: np.ndarray, min_confidence: float = 0.4) -> str: """Convenience method: joins all detected text fragments into one spoken sentence.""" results = self.read_text(frame, min_confidence) if not results: return "" return ". ".join(text for text, _ in results)