from __future__ import annotations import io import pytesseract from fastapi import FastAPI, File, UploadFile from PIL import Image from pytesseract import Output app = FastAPI(title="Local OCR Service", version="0.1.0") @app.get("/health") async def health() -> dict: return {"status": "ok"} @app.post("/ocr") async def ocr(file: UploadFile = File(...)) -> dict: data = await file.read() image = Image.open(io.BytesIO(data)).convert("RGB") structured = pytesseract.image_to_data(image, output_type=Output.DICT) lines = [] width, height = image.size order = 0 for idx, text in enumerate(structured["text"]): text = text.strip() if not text: continue confidence = float(structured["conf"][idx]) / 100.0 x = structured["left"][idx] / width y = structured["top"][idx] / height w = structured["width"][idx] / width h = structured["height"][idx] / height order += 1 lines.append( { "id": f"line_{order}", "text": text, "bbox": [x, y, x + w, y + h], "confidence": max(0.0, min(1.0, confidence)), "reading_order": order, "region_type": "text_line", } ) return { "markdown": "\n".join(line["text"] for line in lines), "lines": lines, "tables": [], }