Spaces:
Running on Zero
Running on Zero
File size: 4,462 Bytes
af072f4 c45e778 af072f4 c45e778 af072f4 c45e778 af072f4 c45e778 af072f4 c45e778 af072f4 e5259bc af072f4 96071cd af072f4 ab8cd3d af072f4 ab8cd3d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | """PP-OCRv6 medium recognition model demo.
Upload a cropped text-line image and get recognized text with a confidence score.
PP-OCRv6_medium_rec is a 19M-parameter text recognition model from PaddlePaddle.
"""
import json
import os
import tempfile
# On ZeroGPU, `import spaces` must come before any torch/CUDA import.
# PaddlePaddle doesn't use torch, but the ZeroGPU runtime still requires
# this import and a @spaces.GPU decorator on the inference function.
import spaces
import gradio as gr
from paddleocr import TextRecognition
# Load model at module scope — PaddlePaddle runs on CPU natively.
MODEL_NAME = "PP-OCRv6_medium_rec"
rec_model = TextRecognition(model_name=MODEL_NAME)
@spaces.GPU(duration=30)
def recognize_text(image):
"""Recognize text from a cropped text-line image.
Args:
image: A file path to an image containing a single line of text.
Returns:
A tuple of (recognized_text, confidence_score, raw_json).
"""
if image is None:
return "No image provided", 0.0, ""
img_path = image if isinstance(image, str) else None
if img_path is None:
with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as f:
image.save(f, format="PNG")
img_path = f.name
try:
output = rec_model.predict(input=img_path, batch_size=1)
results = []
for res in output:
raw_json = getattr(res, "json", None)
if isinstance(raw_json, dict):
data = raw_json
elif isinstance(raw_json, str):
data = json.loads(raw_json)
elif hasattr(res, "to_dict"):
data = res.to_dict()
else:
data = {
"rec_text": getattr(res, "rec_text", str(res)),
"rec_score": getattr(res, "rec_score", 0.0),
}
results.append(data)
if not results:
return "No text recognized", 0.0, ""
# Results may be nested under a "res" key
first = results[0]
if "res" in first:
first = first["res"]
text = first.get("rec_text", "")
score = first.get("rec_score", 0.0)
raw = json.dumps(results, ensure_ascii=False, indent=2)
return text, float(score), raw
except Exception as e:
return f"Error: {e}", 0.0, ""
finally:
if not isinstance(image, str) and os.path.exists(img_path):
os.unlink(img_path)
# --- UI ---
CSS = """
#col-container { max-width: 900px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks() as demo:
with gr.Column(elem_id="col-container"):
gr.Markdown("# PP-OCRv6 Medium Text Recognition")
gr.Markdown(
"Upload a cropped image of a single text line to recognize text. "
"This is the [PP-OCRv6_medium_rec](https://huggingface.co/PaddlePaddle/PP-OCRv6_medium_rec) "
"model — a 19M-parameter OCR recognition model from PaddlePaddle that "
"supports 50 languages."
)
with gr.Row():
with gr.Column(scale=1):
input_image = gr.Image(
label="Text-line image",
type="filepath",
height=200,
)
run_btn = gr.Button("Recognize Text", variant="primary")
with gr.Column(scale=1):
text_output = gr.Textbox(label="Recognized text", interactive=False)
score_output = gr.Number(label="Confidence score", precision=4, interactive=False)
raw_output = gr.Code(label="Raw JSON output", language="json")
gr.Examples(
examples=[
["examples/sample_readme.jpeg"],
["examples/sample_text.png"],
["examples/sample_text2.png"],
["examples/sample_text3.png"],
["examples/sample_text4.png"],
],
inputs=input_image,
outputs=[text_output, score_output, raw_output],
fn=recognize_text,
cache_examples=True,
cache_mode="lazy",
)
run_btn.click(
fn=recognize_text,
inputs=input_image,
outputs=[text_output, score_output, raw_output],
api_name="recognize",
)
if __name__ == "__main__":
demo.launch(mcp_server=True, theme=gr.themes.Citrus(), css=CSS) |