anaksor-ocr: Khmer text detection and recognition

Weights for Khmer (and English/Latin) OCR on documents, receipts and photos of signs. Two models work together. A detector finds the text lines, and a recogniser reads each cropped line. They are the models behind the anaksor-ocr Python package and the demo at ocr.sokhengdin.dev.

Model Architecture Current
Recognition SVTRv2-B encoder + CTC head (GTC and counting side losses in training only) v4
Detection Mobile DBNet++: RepViT backbone + RSEFPN + Adaptive Scale Fusion + DB head DBNet++ v1

The main branch always holds the newest release. Each release is also tagged (rec-v4-det-dbpp-v1; the previous one is rec-v4-det-v3), so you can pin a version.

Use with anaksor-ocr

pip install anaksor-ocr              # ONNX Runtime, no PyTorch
pip install "anaksor-ocr[torch]"     # adds the PyTorch backend (CUDA, Apple MPS)
import anaksor

ocr    = anaksor.OCR()
result = ocr("letter.jpg")
print(result["text"])

The package downloads only the files its backend needs: the .onnx graphs for ONNX Runtime, or .safetensors for PyTorch. It checks each file against the SHA-256 in its model spec and caches it in ~/.cache/anaksor. To pin a release, or to run offline:

ANAKSOR_HF_REVISION=rec-v4-det-v3 anaksor letter.jpg   # a tagged release (anaksor-ocr 0.1.x)
anaksor --fetch-models                                 # download ahead of time
ANAKSOR_WEIGHTS_DIR=./weights anaksor letter.jpg       # use local copies, no network

Neither format runs code when it is loaded.

Files

File What it is
khmer_rec_svtrv2_latest.pth Recognition weights (training checkpoint)
rec_latest.yml Recognition config: architecture, charset, input height 48, up to 140 characters, crop margins
khmer_det_repvit_dbpp_latest.pth Detection weights, mobile DBNet++ (training checkpoint)
det_latest.yml Detection config: architecture, post-processing thresholds
khmer_dict_v3.txt Character set: 211 characters + space
*.safetensors, *.onnx The same models in the formats the anaksor-ocr package loads

Always load a .pth with the .yml from the same revision, because the configs change between versions. To use your own checkpoint in the package, make a spec from its training config first:

python tools/spec_from_config.py rec_latest.yml --out specs/

Download

hf download Sokheng/anaksor-ocr --local-dir weights/huggingface
# a specific release:
hf download Sokheng/anaksor-ocr --revision rec-v4-det-dbpp-v1 --local-dir weights/huggingface

Results

Recognition v4

Line accuracy (the whole line exactly right) / character error rate, after Khmer text normalisation.

Set Lines v3 (previous) v4
Real validation, all 3,878 84.8% / 1.83% 86.7% / 1.38%
↳ Khmer 2,497 91.1% / 0.63% 90.1% / 0.73%
↳ Latin 982 66.9% / 6.98% 76.4% / 4.29%
↳ Mixed Khmer + Latin 331 96.4% / 0.24% 95.5% / 0.34%
Synthetic long lines 3,000 97.8% / 0.45% 98.3% / 0.39%

v4 is much better on Latin text. On Khmer-only lines it is about one point behind v3.

Detection: mobile DBNet++ v1

Precision / recall / hmean.

Set Chinese pretrained v3 (previous) DBNet++ v1
KhmerST validation (photos) 0.796 / 0.925 / 0.856 0.751 / 0.793 / 0.771 0.725 / 0.821 / 0.770
HierText validation (English on photos) 0.526 / 0.547 / 0.537 0.755 / 0.688 / 0.720 0.763 / 0.689 / 0.724
Synthetic pages 0.781 / 0.949 / 0.857 0.999 / 0.997 / 0.998 1.000 / 0.998 / 0.999

Upright text is on par with v3. The gain is on rotated text: hmean on 100 HierText validation images, turned by each angle:

Rotation 0° 45° 90° 135° 180°
v3 0.686 0.303 0.468 0.314 0.682
DBNet++ v1 0.690 0.421 0.591 0.467 0.677

KhmerST labels only some of the text in each image. The unlabelled text is marked "don't care" using the Chinese model's detections, which flatters that model's KhmerST score. HierText is the fairer comparison for English on photos.

Training

  • Recognition: fine-tuned from OpenOCR's Chinese-pretrained SVTRv2-B on:

    • KhmerST crops, 62k printed lines, 4.2k handwritten lines, c_khmer_gemma_ocr_train and khmer-hanuman-100k;
    • HierText English line crops;
    • 300k synthetic lines rendered with HarfBuzz from Khmer dictionary and Wikipedia text.

    40% of the real training crops get random margins, like the boxes a detector produces.

  • Detection: mobile DBNet++ (Liao et al., TPAMI 2022, arXiv:2202.10304): detection v3 plus an Adaptive Scale Fusion block (+21k parameters, 3.15 M in all), fine-tuned from v3 for 40 epochs on the same data (KhmerST, synthetic pages, receipts and signs with Latin display fonts, 3,000 HierText images; unlabelled KhmerST text pseudo-labelled when the recogniser reads it with high confidence), now with augmentation at every angle.

  • Labels and predictions go through the same Khmer normaliser. It removes ZWSP/ZWNJ, puts the marks in each character cluster in a fixed order, and follows UTN #61.

Limitations

  • Trained mainly on printed Khmer. Handwriting and decorative fonts are weaker.
  • Latin text in photos is the weakest case (76% line accuracy above).
  • The recogniser reads one line per crop. Lines longer than 20× their height are read as overlapping windows and joined back together at whole Khmer clusters. anaksor-ocr does this for you.

License

Weights: Apache-2.0. The training data includes HierText (CC BY-SA 4.0) and the Hugging Face datasets listed above, each under its own license.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Paper for Sokheng/anaksor-ocr