Handwritten Greek OCR
An ONNX model for recognizing handwritten Greek text, fine-tuned from PaddlePaddle's PP-OCRv5 server-grade recognition checkpoint. This fine-tune adapts it specifically to the Greek alphabet.
The model was trained on a synthetic dataset of 50,000 images generated using handwritten Greek fonts and containing up to 50 characters (including spaces).
Examples
| Input Image | Predicted Text | Confidence |
|---|---|---|
![]() |
η διαδικασία είναι περίπλοκη | 0.9450 |
![]() |
η διαδικασία είναι περίπλοκη | 0.9595 |
![]() |
Ο Γιώργος ο Γιάννης (missed the comma) | 0.8893 |
![]() |
Ο Γιώργος, ο Γιάννης | 0.9575 |
Input & Preprocessing
- Color format: BGR (converted from RGB to match PaddleOCR training convention)
- Resize: image is scaled to height
48px, width padded to320pxwith zeros - Normalization: pixel values normalized to
[-1, 1]
Limitations
- Designed for single text-line images — for multi-line documents, segment lines before running inference.
- Can mostly recognise Greek characters and punctuation .
Quick Start
Installation
pip install onnxruntime pillow numpy
# For GPU support:
pip install onnxruntime-gpu pillow numpy
Inference
from PIL import Image
import numpy as np
import math
import onnxruntime as ort
def resize_norm_img(img, imgH=48, imgW=320):
h, w = img.shape[:2]
ratio = w / float(h)
resized_w = imgW if math.ceil(imgH * ratio) > imgW else int(math.ceil(imgH * ratio))
pil_img = Image.fromarray(img)
resized_image = np.array(pil_img.resize((resized_w, imgH), Image.BILINEAR)).astype('float32')
resized_image = resized_image.transpose((2, 0, 1)) / 255.0
resized_image = (resized_image - 0.5) / 0.5
padding_im = np.zeros((3, imgH, imgW), dtype=np.float32)
padding_im[:, :, :resized_w] = resized_image
return np.expand_dims(padding_im, axis=0)
def load_dict(dict_path):
with open(dict_path, "rb") as f:
lines = f.readlines()
character = [line.decode('utf-8').strip() for line in lines] + [" "]
return ['<blank>'] + character
def decode(preds, character):
preds_idx = preds.argmax(axis=2)[0]
preds_prob = preds.max(axis=2)[0]
char_list, conf_list = [], []
for i, idx in enumerate(preds_idx):
if idx != 0 and not (i > 0 and idx == preds_idx[i - 1]):
char_list.append(character[idx])
conf_list.append(preds_prob[i])
text = ''.join(char_list)
confidence = float(np.mean(conf_list)) if conf_list else 0.0
return text, confidence
# Load model and dictionary
session = ort.InferenceSession("model.onnx", providers=['CUDAExecutionProvider', 'CPUExecutionProvider'])
characters = load_dict("greek_dict.txt")
# Run on an image
img = np.array(Image.open("your_image.png").convert("RGB"))
img_bgr = img[:, :, ::-1] # RGB → BGR
input_tensor = resize_norm_img(img_bgr)
outputs = session.run(None, {session.get_inputs()[0].name: input_tensor})
text, confidence = decode(outputs[0], characters)
print(f"Recognized: {text}")
print(f"Confidence: {confidence:.4f}")
Model Details
| Property | Value |
|---|---|
| Task | Handwritten Greek text recognition |
| Architecture | SVTR_HGNet (PPHGNetV2_B4 backbone + SVTR neck, CTC head) |
| Format | ONNX |
| Input size | 3 × 48 × 320 (C × H × W) |
| Language | Greek (el) |
| Runtime | ONNX Runtime (CPU & CUDA) |
Repository Files
├── model.onnx # ONNX model weights
├── greek_dict.txt # Greek character dictionary
├── inference.py # Ready-to-run inference script
└── test.png # Sample test image
Citation
If you use this model, please cite this repository:
@misc{handwritten-greek-ocr,
title = {Handwritten Greek OCR},
author = {Iordanis Sapidis},
year = {2026},
url = {https://huggingface.co/iordanissap/handwritten-greek-ocr}
}
- Downloads last month
- 367



