feat(paddleocr): add PaddleOCR OCR service (Docker images, server, tests, docs) and CI workflows

This commit is contained in:
2026-01-16 13:23:01 +00:00
parent 67c38eeb67
commit bec379e9ca
10 changed files with 624 additions and 71 deletions

View File

@@ -26,6 +26,7 @@ logger = logging.getLogger(__name__)
# Environment configuration
OCR_LANGUAGE = os.environ.get('OCR_LANGUAGE', 'en')
# GPU is controlled via CUDA_VISIBLE_DEVICES environment variable
USE_GPU = os.environ.get('CUDA_VISIBLE_DEVICES', '') != '-1'
# Initialize FastAPI app
@@ -72,19 +73,29 @@ class HealthResponse(BaseModel):
gpu_enabled: bool
def get_ocr() -> PaddleOCR:
def get_ocr(lang: Optional[str] = None) -> PaddleOCR:
"""Get or initialize the OCR instance"""
global ocr_instance
if ocr_instance is None:
logger.info(f"Initializing PaddleOCR with language={OCR_LANGUAGE}, use_gpu={USE_GPU}")
ocr_instance = PaddleOCR(
use_angle_cls=True,
lang=OCR_LANGUAGE,
use_gpu=USE_GPU,
show_log=False
)
logger.info("PaddleOCR initialized successfully")
return ocr_instance
use_lang = lang or OCR_LANGUAGE
# Return cached instance if same language
if ocr_instance is not None and lang is None:
return ocr_instance
logger.info(f"Initializing PaddleOCR with language={use_lang}, use_gpu={USE_GPU}")
new_ocr = PaddleOCR(
use_angle_cls=True,
lang=use_lang,
use_gpu=USE_GPU,
show_log=False
)
# Cache the default language instance
if lang is None:
ocr_instance = new_ocr
logger.info("PaddleOCR initialized successfully")
return new_ocr
def decode_base64_image(base64_string: str) -> np.ndarray:
@@ -176,20 +187,12 @@ async def ocr_base64(request: OCRRequest):
image = decode_base64_image(request.image)
# Get OCR instance (use request language if provided)
ocr = get_ocr()
# If a different language is requested, create a new instance
if request.language and request.language != OCR_LANGUAGE:
logger.info(f"Creating OCR instance for language: {request.language}")
temp_ocr = PaddleOCR(
use_angle_cls=True,
lang=request.language,
use_gpu=USE_GPU,
show_log=False
)
result = temp_ocr.ocr(image, cls=True)
ocr = get_ocr(request.language)
else:
result = ocr.ocr(image, cls=True)
ocr = get_ocr()
result = ocr.ocr(image, cls=True)
# Process results
results = process_ocr_result(result)
@@ -228,20 +231,12 @@ async def ocr_upload(
image_array = np.array(image)
# Get OCR instance
ocr = get_ocr()
# If a different language is requested, create a new instance
if language and language != OCR_LANGUAGE:
logger.info(f"Creating OCR instance for language: {language}")
temp_ocr = PaddleOCR(
use_angle_cls=True,
lang=language,
use_gpu=USE_GPU,
show_log=False
)
result = temp_ocr.ocr(image_array, cls=True)
ocr = get_ocr(language)
else:
result = ocr.ocr(image_array, cls=True)
ocr = get_ocr()
result = ocr.ocr(image_array, cls=True)
# Process results
results = process_ocr_result(result)