Views
No views yet
| Split | CER |
|---|---|
| Validation | 2.7% |
| Hold-out test | 3.7% |
10.5281/zenodo.7050270), which achieves roughly 20% CER on this material out of the box. Fine-tuning was done using resize='both' to extend the output layer for Jawi-specific characters absent from the base model's alphabet.transformers model. Use it via the Kraken library with huggingface_hub to download the weights.pip install "kraken>=6.0.0,<7.0.0" huggingface_hub Pillow1from huggingface_hub import hf_hub_download
2from PIL import Image
3from kraken.lib import models
4from kraken import rpred
5from kraken.containers import Segmentation, BaselineLine
6
7# Download the model from HuggingFace
8model_path = hf_hub_download(
9 repo_id="culturalheritagenus/jawi-ocr", # replace with actual repo ID
10 filename="jawi_rec.mlmodel", # replace with actual filename
11)
12
13# Load the Kraken recognition model
14rec_model = models.load_any(model_path)
15
16# Open a pre-cropped single-line image
17im = Image.open("line_image.png")
18if im.mode not in ("RGB", "L", "1"):
19 im = im.convert("RGB")
20
21w, h = im.size
22
23# Construct a synthetic single-line segmentation container.
24# The baseline sits at ~75% of the image height (appropriate for
25# Arabic-script text where characters hang from above).
26# The boundary covers the full image, inset by 1px to avoid edge rejection.
27baseline_y = int(h * 0.75)
28
29line = BaselineLine(
30 id="line_0",
31 baseline=[(1, baseline_y), (w - 1, baseline_y)],
32 boundary=[(1, 1), (w - 1, 1), (w - 1, h - 1), (1, h - 1), (1, 1)],
33 text=None,
34 base_dir="R",
35)
36
37seg = Segmentation(
38 type="baselines",
39 imagename="",
40 text_direction="horizontal-rl",
41 script_detection=False,
42 lines=[line],
43 regions={},
44 line_orders=[],
45)
46
47# Run recognition with LTR BiDi base direction
48pred_it = rpred.rpred(rec_model, im, seg, bidi_reordering="L")
49
50for record in pred_it:
51 print(record.prediction)
52 for char, polygon, conf in zip(record.prediction, record.cuts, record.confidences):
53 print(f" {char} conf={conf:.3f} polygon={polygon}")record object contains three aligned lists: record.prediction (the full recognised string), record.cuts (per-character bounding polygons in pixel coordinates relative to the input image), and record.confidences (per-character confidence values between 0 and 1).text_direction='horizontal-rl' and base_dir='R' because these control how Kraken feeds the line image to the neural network — the LSTM must process the pixels right-to-left for Arabic-script text. The bidi_reordering='L' parameter is a separate post-processing step that reorders the output string using the Unicode BiDi algorithm with LTR as the paragraph base direction, so that Arabic/Jawi runs appear as embedded RTL spans. This makes the output suitable for direct display in any Unicode-aware environment..mlmodel file and pass it as the base model to Kraken's training API:1from kraken.lib.train import RecognitionModel, KrakenTrainer
2
3model = RecognitionModel(
4 training_data=train_files, # list of PAGE XML paths
5 evaluation_data=eval_files,
6 format_type="page",
7 resize="both", # extend alphabet for new characters
8 model=model_path, # path to the downloaded .mlmodel
9 hyper_params={"augment": True},
10)
11
12trainer = KrakenTrainer(accelerator="gpu", devices=1)
13trainer.fit(model)| File | Description |
|---|---|
*.mlmodel | Kraken model file (neural network weights, codec, and metadata) |