import atexit import functools from queue import Queue from threading import Event, Thread from paddleocr import PaddleOCR, draw_ocr from PIL import Image import gradio as gr LANG_CONFIG = { "ch": {"num_workers": 1}, "en": {"num_workers": 1}, "fr": {"num_workers": 1}, "german": {"num_workers": 1}, "korean": {"num_workers": 1}, "japan": {"num_workers": 1}, } CONCURRENCY_LIMIT = 2 class PaddleOCRModelManager: def __init__(self, num_workers, model_factory): self._model_factory = model_factory self._queue = Queue() self._workers = [] self._model_initialized_event = Event() for _ in range(num_workers): worker = Thread(target=self._worker, daemon=True) worker.start() self._model_initialized_event.wait() self._model_initialized_event.clear() self._workers.append(worker) def infer(self, *args, **kwargs): result_queue = Queue(maxsize=1) self._queue.put((args, kwargs, result_queue)) success, payload = result_queue.get() if success: return payload else: raise payload def close(self): for _ in self._workers: self._queue.put(None) def _worker(self): model = self._model_factory() self._model_initialized_event.set() while True: item = self._queue.get() if item is None: break args, kwargs, result_queue = item try: result = model.ocr(*args, **kwargs) result_queue.put((True, result)) except Exception as e: result_queue.put((False, e)) def create_model(lang): return PaddleOCR(lang=lang, use_angle_cls=True, use_gpu=False) model_managers = {} for lang, config in LANG_CONFIG.items(): model_managers[lang] = PaddleOCRModelManager( config["num_workers"], functools.partial(create_model, lang=lang) ) def close_model_managers(): for manager in model_managers.values(): manager.close() atexit.register(close_model_managers) def inference(img, lang): ocr = model_managers[lang] result = ocr.infer(img, cls=True) if not result or not result[0]: return Image.open(img) result = result[0] image = Image.open(img).convert("RGB") boxes = [line[0] for line in result] txts = [line[1][0] for line in result] scores = [line[1][1] for line in result] im_show = draw_ocr( image, boxes, txts, scores, font_path="./simfang.ttf" ) return im_show title = "PaddleOCR" description = """ Gradio demo for PaddleOCR. Supported languages: Chinese, English, French, German, Korean, Japanese. Upload an image and select the language. """ examples = [ ["en_example.jpg", "en"], ["cn_example.jpg", "ch"], ["jp_example.jpg", "japan"], ] css = ".output_image, .input_image {height: 40rem !important; width: 100% !important;}" demo = gr.Interface( fn=inference, inputs=[ gr.Image(type="filepath", label="Input"), gr.Dropdown( choices=list(LANG_CONFIG.keys()), value="en", label="Language" ), ], outputs=gr.Image(type="pil", label="Output"), title=title, description=description, examples=examples, cache_examples=False, css=css, concurrency_limit=CONCURRENCY_LIMIT, ) demo.launch()