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 | RepViT backbone + DBNet head | v3 |
The main branch always holds the newest release. Each release is also tagged
(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 --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_db_latest.pth |
Detection weights (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-v3 --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 v3
Precision / recall / hmean.
| Set | Chinese pretrained | v2 (previous) | v3 |
|---|---|---|---|
| KhmerST validation (photos) | 0.796 / 0.925 / 0.856 | 0.681 / 0.409 / 0.511 | 0.751 / 0.793 / 0.771 |
| HierText validation (English on photos) | 0.526 / 0.547 / 0.537 | 0.529 / 0.227 / 0.317 | 0.755 / 0.688 / 0.720 |
| Synthetic pages | 0.744 / 0.930 / 0.827 | 0.997 / 0.997 / 0.997 | 0.998 / 0.998 / 0.998 |
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: fine-tuned from detection v2 on KhmerST, synthetic pages, receipts and signs (with Latin display fonts), and 3,000 HierText images. Unlabelled KhmerST text is pseudo-labelled when the recogniser reads it with high confidence.
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.