| 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": [], |
| } |
|
|