Spaces:
Running
Running
| from fastapi import APIRouter, File, UploadFile, Form, Depends, HTTPException, status | |
| from fastapi.responses import JSONResponse | |
| from src.services.image_processor import image_processor | |
| from src.services.ocr_engine import ocr_service | |
| from src.services.markdown_formatter import format_ocr_result | |
| from src.api.dependencies import verify_api_key | |
| router = APIRouter() | |
| def health_check(): | |
| """Unauthenticated endpoint to check server health.""" | |
| return {"status": "healthy"} | |
| async def extract_text( | |
| image: UploadFile = File(...), | |
| lang: str = Form("en", description="Target language code (e.g. 'en', 'hi', 'ar') or 'auto' for automatic language detection."), | |
| api_key: str = Depends(verify_api_key) | |
| ): | |
| """ | |
| Receives an image file via multipart form, processes it with PaddleOCR, | |
| and returns both plain text and structured Markdown in the JSON response. | |
| Supported lang values: 'auto' (automatic detection), or specific codes like 'en', 'hi', 'ar', 'es', 'pt', etc. | |
| Response shape: | |
| { | |
| "success": true, | |
| "data": { | |
| "result": "<plain text, newline-joined>", | |
| "markdown": "<structured Markdown with headings, tables, key-values>", | |
| "fileName": "<original filename>" | |
| } | |
| } | |
| """ | |
| try: | |
| # Validate mime type | |
| if not image.content_type.startswith("image/"): | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="Uploaded file is not a supported image format." | |
| ) | |
| # Read raw bytes | |
| image_bytes = await image.read() | |
| # Preprocess: EXIF correction β resolution guard β CLAHE β unsharp mask | |
| img_np = image_processor.process_bytes_to_numpy(image_bytes) | |
| # Run OCR β returns raw bounding-box result list (not yet formatted) | |
| raw_result = await ocr_service.run_ocr_raw(img_np, lang) | |
| # Convert raw result β plain text + structured Markdown | |
| plain_text, markdown_text = format_ocr_result(raw_result) | |
| return { | |
| "success": True, | |
| "data": { | |
| "result": plain_text, | |
| "markdown": markdown_text, | |
| "fileName": image.filename or "uploaded_image.jpg" | |
| } | |
| } | |
| except HTTPException as he: | |
| raise he | |
| except Exception as e: | |
| import traceback | |
| traceback.print_exc() | |
| return JSONResponse( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| content={ | |
| "success": False, | |
| "error": f"OCR processing failed: {str(e)}" | |
| } | |
| ) | |