| from fastapi import FastAPI, HTTPException, UploadFile, File
|
| from pydantic import BaseModel
|
| from typing import List, Optional, Dict, Any
|
| import re
|
| import uvicorn
|
| import cv2
|
| import base64
|
| import numpy as np
|
| from image_enhancing import ImageEnhancer
|
|
|
| app = FastAPI(title="Preprocessing Service", description="Enhances images and normalizes text for OCR.")
|
| enhancer = ImageEnhancer(sigma=1.2)
|
|
|
| class PreprocessRequest(BaseModel):
|
| text: str
|
| source: Optional[str] = "unknown"
|
|
|
| class PreprocessResponse(BaseModel):
|
| status: str
|
| normalized_text: str
|
| tokens: List[str]
|
|
|
| @app.get("/health")
|
| async def health_check():
|
| """Returns the health status of the Preprocessing service."""
|
| return {"status": "healthy", "service": "preprocessing"}
|
|
|
| def clean_ocr_errors(text: str) -> str:
|
| """Fix common OCR misreadings contextually."""
|
|
|
| replacements = {
|
| '×': '*',
|
| '÷': '/',
|
| '−': '-',
|
| '–': '-',
|
| ' x ': ' * ',
|
| '**': '^'
|
| }
|
| for old, new in replacements.items():
|
| text = text.replace(old, new)
|
|
|
| return text.strip()
|
|
|
| def tokenize_math(text: str) -> List[str]:
|
| """Tokenize the mathematical expression into components."""
|
|
|
| pattern = re.compile(r'(\d+\.?\d*|[a-zA-Z]+|[+\-*/=()^])')
|
| tokens = [t.strip() for t in pattern.findall(text) if t.strip()]
|
| return tokens
|
|
|
| @app.post("/enhance_image")
|
| async def enhance_image(file: UploadFile = File(...)):
|
| """
|
| Accepts an image file, applies MVM² noise reduction and lighting normalization,
|
| and returns the enhanced image as a base64 string along with quality metadata.
|
| """
|
| try:
|
| contents = await file.read()
|
| enhanced_img, metadata = enhancer.enhance(contents)
|
|
|
|
|
| _, buffer = cv2.imencode('.png', enhanced_img)
|
| img_base64 = base64.b64encode(buffer).decode('utf-8')
|
|
|
| return {
|
| "status": "success",
|
| "metadata": metadata,
|
| "enhanced_image_base64": img_base64
|
| }
|
| except Exception as e:
|
| import traceback
|
| traceback.print_exc()
|
| raise HTTPException(status_code=500, detail=str(e))
|
|
|
| @app.post("/preprocess", response_model=PreprocessResponse)
|
| async def preprocess_text(request: PreprocessRequest):
|
| """
|
| Accepts raw text (from OCR or direct input), normalizes it, cleans common OCR errors,
|
| and tokenizes it into mathematical components.
|
| This structured data will subsequently be sent to the Representation Service.
|
| """
|
| if not request.text.strip():
|
| raise HTTPException(status_code=400, detail="Text cannot be empty.")
|
|
|
|
|
| cleaned_text = clean_ocr_errors(request.text)
|
|
|
|
|
| tokens = tokenize_math(cleaned_text)
|
|
|
| return {
|
| "status": "success",
|
| "normalized_text": cleaned_text,
|
| "tokens": tokens
|
| }
|
|
|
| if __name__ == "__main__":
|
| uvicorn.run(app, host="0.0.0.0", port=8001)
|
|
|