| from fastapi import FastAPI, UploadFile, File, Form, HTTPException |
| from fastapi.responses import JSONResponse |
| from PIL import Image |
| import numpy as np |
| import cv2 |
| import io |
| import requests |
| from typing import Optional |
| from pydantic import BaseModel |
| from rapidocr_onnxruntime import RapidOCR |
|
|
| app = FastAPI(title="OCR API", description="RapidOCR API Service") |
| engine = RapidOCR() |
|
|
| def process_ocr(image: np.ndarray, use_det: bool, use_cls: bool, use_rec: bool) -> list: |
| """Xử lý OCR và trả về kết quả""" |
| img_bgr = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) |
| result, _ = engine(img_bgr, use_det=use_det, use_cls=use_cls, use_rec=use_rec) |
| |
| if not result: |
| return [] |
| |
| texts = [] |
| for item in result: |
| if len(item) == 3: |
| box, text, score = item |
| texts.append({ |
| "text": text, |
| "confidence": float(score), |
| "bbox": box.tolist() if hasattr(box, 'tolist') else box |
| }) |
| elif len(item) == 2: |
| _, text = item |
| texts.append({ |
| "text": str(text), |
| "confidence": None, |
| "bbox": None |
| }) |
| |
| return texts |
|
|
| @app.post("/ocr") |
| async def ocr_from_file( |
| file: UploadFile = File(..., description="Image file to process"), |
| use_det: bool = Form(True, description="Use text detection"), |
| use_cls: bool = Form(True, description="Use classification"), |
| use_rec: bool = Form(True, description="Use recognition") |
| ): |
| if not file.content_type or not file.content_type.startswith('image/'): |
| raise HTTPException(status_code=400, detail="File must be an image") |
| |
| try: |
| contents = await file.read() |
| image = Image.open(io.BytesIO(contents)) |
| |
| if image.mode != 'RGB': |
| image = image.convert('RGB') |
| |
| img_np = np.array(image) |
| results = process_ocr(img_np, use_det, use_cls, use_rec) |
| |
| return JSONResponse(content={ |
| "success": True, |
| "texts": [item["text"] for item in results], |
| "details": results, |
| "num_texts": len(results) |
| }) |
| |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=f"Error: {str(e)}") |
|
|
| @app.get("/health") |
| async def health_check(): |
| """Health check endpoint""" |
| return {"status": "healthy", "service": "XOCR AI"} |
|
|
| if __name__ == "__main__": |
| import uvicorn |
| uvicorn.run(app, host="0.0.0.0", port=7860) |