"""PaddleOCR Remote Service — PP-OCRv5 Latin auf x86_64.""" import io import os import numpy as np from fastapi import FastAPI, File, Header, HTTPException, UploadFile from PIL import Image app = FastAPI(title="PaddleOCR Service") _engine = None API_KEY = os.environ.get("PADDLEOCR_API_KEY", "") def get_engine(): global _engine if _engine is None: from paddleocr import PaddleOCR # PaddleOCR >= 3.x: use ocr_version param; fallback for older API try: _engine = PaddleOCR( lang="en", ocr_version="PP-OCRv5", use_angle_cls=True, show_log=False, ) except (ValueError, TypeError): _engine = PaddleOCR( lang="latin", use_angle_cls=True, show_log=False, ) return _engine @app.get("/health") def health(): return {"status": "ok", "model": "PP-OCRv5-latin"} @app.post("/ocr") async def ocr( file: UploadFile = File(...), x_api_key: str = Header(default=""), ): if API_KEY and x_api_key != API_KEY: raise HTTPException(status_code=401, detail="Invalid API key") img_bytes = await file.read() img = Image.open(io.BytesIO(img_bytes)).convert("RGB") img_np = np.array(img) engine = get_engine() result = engine.ocr(img_np) words = [] for line in result[0] or []: box, (text, conf) = line[0], line[1] x_min = min(p[0] for p in box) y_min = min(p[1] for p in box) x_max = max(p[0] for p in box) y_max = max(p[1] for p in box) words.append( { "text": text, "left": int(x_min), "top": int(y_min), "width": int(x_max - x_min), "height": int(y_max - y_min), "conf": round(conf * 100, 1), } ) return { "words": words, "image_width": img_np.shape[1], "image_height": img_np.shape[0], }