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.