Downloads · 30 days
13
15% of all-time downloads
GaborMadarasz/paddleocr-ppocr6-mek-finetuned
paddleocr-ppocr6-mek-finetuned is a image-to-text model from GaborMadarasz. Use it when you need a caption or text from an image. The card lists the license as apache-2.0.
Fine-tuned text recognition model based on PP-OCRv6 small (PP-OCRv6smallrec, ~5.2M parameters), specialized for Hungarian antiqua typography from the 1880–1930 period, with emphasis on correct recognition of Hungarian…
Downloads · 30 days
13
15% of all-time downloads
All-time downloads
84
Public
Repo size
58.8 MB
Likes
0
Public
Click a slice to open those files.
.pdiparams58.8 MB · 100%
From the Hugging Face model README
Fine-tuned text recognition model based on PP-OCRv6 small (PP-OCRv6_small_rec, ~5.2M parameters),
specialized for Hungarian antiqua typography from the 1880–1930 period,
with emphasis on correct recognition of Hungarian-specific characters: Ő, Ű, É, Í (uppercase accented letters).
| Property | Value |
|---|---|
| Base model | PP-OCRv6_small_rec (PaddleOCR 3.x) |
| Parameters | ~5.2M |
| Architecture | SVTR-LCNet + NRTR hybrid (CTC + attention, MultiHead) |
| Input | Text-line image crops (variable width × 48px height) |
| Output | UTF-8 string (Hungarian text) |
| Training epochs | 20 |
| Best epoch | 12 (acc: 0.9891, norm_edit_dis: 0.9988) |
| Training hardware | 2× NVIDIA Tesla T4 (Kaggle) |
| Framework | PaddlePaddle 3.0 / PaddleOCR 3.x |
| Inference engine | paddle (static graph) |
Dataset: GaborMadarasz/synthetic_OCR_dataset_MEK
Synthetic text-line images generated from digitized books of the Magyar Elektronikus Könyvtár (MEK), covering Hungarian antiqua typeset publications from approximately 1880 to 1930.
Key characteristics:
| Parameter | Value |
|---|---|
| Base pretrained weights | PP-OCRv6_small_rec official Latin weights |
| Character dictionary | Custom Hungarian (incl. all accented chars) |
| Batch size | 128 per card × 2 cards |
| Optimizer | Adam (β1=0.9, β2=0.999) |
| Learning rate | 5e-5, Cosine decay, 2 epoch warmup |
| Regularizer | L2 (3e-5) |
| Loss | CTC + NRTR (MultiLoss) |
| Max text length | 25 |
| Image shape | 3 × 48 × 320 |
| Multi-GPU | paddle.distributed.launch on 2× T4 |
This model is distributed as a PaddlePaddle static inference model.
The PP-OCRv6 rec architecture exports to a combined format (no separate .pdmodel file):
├── config.json # HuggingFace metadata
├── inference.json # Character dictionary (vocabulary)
├── inference.pdiparams # Model weights + graph (combined static format)
├── inference.yml # PaddleX pipeline config
└── README.md
pip install paddlepaddle-gpu paddleocr>=3.0.3 huggingface_hub
# ============================================================
# Inference – GaborMadarasz/paddleocr-ppocr6-mek-finetuned
# ============================================================
import os
import numpy as np
import cv2
from huggingface_hub import snapshot_download
from paddleocr import TextRecognition
# ------------------------------------------------------------
# 1. Download model from HuggingFace
# ------------------------------------------------------------
MODEL_DIR = snapshot_download(
repo_id="GaborMadarasz/paddleocr-ppocr6-mek-finetuned",
repo_type="model",
)
print(f"Model downloaded to: {MODEL_DIR}")
# ------------------------------------------------------------
# 2. Load model
# ------------------------------------------------------------
model = TextRecognition(
model_name="PP-OCRv6_small_rec",
model_dir=MODEL_DIR,
engine="paddle", # required for static graph (.pdiparams) format
device="gpu", # or "cpu"
)
# ------------------------------------------------------------
# 3. Smoke test – synthetic Hungarian text image
# ------------------------------------------------------------
def create_smoke_test_image(
text: str = "Árvíztűrő tükörfúrógép ŐŰÉÍ",
save_path: str = "/tmp/smoke_test.jpg",
) -> str:
"""Render a text-line image with PIL for smoke testing."""
from PIL import Image, ImageDraw, ImageFont
img_h, img_w = 48, 640
img = Image.new("RGB", (img_w, img_h), color=(255, 255, 255))
draw = ImageDraw.Draw(img)
# Try to load a system font; fall back to default if unavailable
font = None
for font_path in [
"/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf",
"/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf",
"/usr/share/fonts/truetype/freefont/FreeSerif.ttf",
]:
if os.path.exists(font_path):
font = ImageFont.truetype(font_path, size=32)
print(f"Font loaded: {font_path}")
break
if font is None:
font = ImageFont.load_default()
print("Warning: using PIL default font – accented chars may not render correctly")
draw.text((8, 4), text, fill=(0, 0, 0), font=font)
img.save(save_path)
print(f"Smoke test image saved: {save_path} (text: '{text}')")
return save_path
SMOKE_IMG = create_smoke_test_image()
# ------------------------------------------------------------
# 4. Single image inference
# ------------------------------------------------------------
def recognize(img_path: str) -> dict:
output = model.predict(input=img_path, batch_size=1)
for res in output:
return {
"text": res.json["res"]["rec_text"],
"score": res.json["res"]["rec_score"],
"image": img_path,
}
# ------------------------------------------------------------
# 5. Batch inference
# ------------------------------------------------------------
def recognize_batch(img_paths: list, batch_size: int = 8) -> list:
results = []
output = model.predict(input=img_paths, batch_size=batch_size)
for res in output:
results.append({
"text": res.json["res"]["rec_text"],
"score": res.json["res"]["rec_score"],
"image": res.json["res"]["input_path"],
})
return results
# ------------------------------------------------------------
# 6. Run smoke test
# ------------------------------------------------------------
result = recognize(SMOKE_IMG)
print("\n=== Smoke test result ===")
print(f" input : {result['image']}")
print(f" text : {result['text']}")
print(f" score : {result['score']:.4f}")
# ------------------------------------------------------------
# 7. Example usage
# ------------------------------------------------------------
if __name__ == "__main__":
import sys, glob
img_paths = sys.argv[1:] if len(sys.argv) > 1 else []
if not img_paths:
print("\nUsage: python infer.py image1.jpg image2.jpg ...")
print("No images provided – smoke test result above is the output.")
sys.exit(0)
if len(img_paths) == 1:
r = recognize(img_paths[0])
print(f"\n[{r['image']}]")
print(f" text : {r['text']}")
print(f" score : {r['score']:.4f}")
else:
results = recognize_batch(img_paths)
for r in results:
print(f"[{r['image']}] → \"{r['text']}\" (score: {r['score']:.4f})")
Note: The model expects pre-cropped single text-line images. For full-page OCR, use a text detection model upstream (e.g.
PP-OCRv6_server_det) to detect and crop individual text lines first.
Results on the held-out validation set (MEK synthetic):
| Metric | Value |
|---|---|
| Accuracy (best epoch 12) | 0.9891 |
| Norm. edit distance | 0.9988 |
| Final epoch accuracy (20) | 0.9830 |
End-to-end CER evaluation on the annotated 25-page MEK baseline will be published here once available.
| Model | Mean CER |
|---|---|
| PP-OCRv6_small_rec (this model, fine-tuned) | pending |
| DeepSeek-OCR baseline | ~2.08% |
engine="paddle" parameter is required; the transformers and paddle_dynamic
engines are not supported without additional weight conversion.If you use this model, please cite the base architecture:
@misc{ppocr2020,
title = {PaddleOCR: Awesome multilingual OCR toolkits based on PaddlePaddle},
author = {PaddlePaddle Authors},
year = {2020},
url = {https://github.com/PaddlePaddle/PaddleOCR}
}
Gábor Madarász — Hungarian NLP hobby project.
Part of a broader effort to improve OCR and NLP tooling for the Hungarian language.
HuggingFace: GaborMadarasz