Chakkhu α αααα»: Khmer + English OCR
Chakkhu (α αααα», "eye") reads Khmer and English text lines from pictures: documents, old printed and typewritten pages, scans, phone photos of paper, screenshots, chat pictures and signs. It is small (18.6M parameters), runs on a CPU, and tells you how sure it is about every line.
- 4.50% character error rate on the full KHOB benchmark (all 4,018 real text lines, never trained on); Netra-OCR 5.87%
- 2.09% on held-out 1990sβ2000s Cambodian government decrees (old print, typewriter, show-through)
- a confidence (0β1) for every line: the most sure half of lines had 0.7% errors, the least sure 10% had 9%
- about 140 ms per line on a laptop CPU, ~20 ms on a GPU
- writes whole Khmer letter clusters (ααααααΈ = 1 step), so subscripts and left-drawn vowels come out in typed order
Demo + free API: INGMUYLEANG/chakkhu-demo Β· Made by Ing Muyleang.
Results (KHOB, all 4,018 lines)
| Model | Character errors (CER) β | Lines fully right β |
|---|---|---|
| Tesseract 5 (khm+eng, best) | 20.55% | 16.5% |
| Netra-OCR | 5.87% | 56.9% |
| Chakkhu | 4.50% | 58.8% |
By picture kind (CER %):
| KHOB task | Tesseract 5 | Netra-OCR | Chakkhu |
|---|---|---|---|
| clean document | 12.8 | 5.02 | 2.26 |
| sent through Messenger | 14.0 | 6.16 | 2.85 |
| scanned | 13.8 | 4.55 | 2.43 |
| phone-scanned | 19.1 | 4.13 | 3.27 |
| street, day | 31.8 | 5.78 | 6.41 |
| street, night | 35.3 | 10.64 | 11.17 |
| short lines (β€ 10 chars) | 51.8 | 22.41 | 8.73 |
| English / numbers only | 40.8 | 21.95 | 24.58 |
All models were scored by us with the same script, the same line crops and the same Khmer text normalization
(chakkhu/khnormal.py: one fixed order inside every cluster, split vowels joined, invisible characters removed β
NFC alone does not do this for Khmer). KHOB level-1 tasks 2β4 use the task-1 boxes aligned to each picture; two
pages that show a different letter were left out. The reader's CTC weight (0.5) was set before scoring; 0.3 and
0.7 give 4.62% and 4.59%.
Old government documents (12 held-out pages of 1993β2003 royal decrees, laws and sub-decrees, never trained on; labels: Gemini's reading, kept where it agreed with Chakkhu): previous version 3.62% β 2.09% CER, 51.7% β 66.8% lines fully right.
Weaker on: street signs (decorative fonts, night photos), English-only lines. Handwriting: some (2,311 real lines in training), not measured yet.
How it works
line picture (grey, 64 px high)
β CNN ResNet blocks: 64 Γ W β 2 rows Γ W/8 columns
β Transformer 6 layers, d 320, sees the whole line
ββ CTC head per column: a cluster or <blank> (fast draft, letter count)
ββ decoder 3 layers, writes one Khmer cluster per step; first trained as a language model on Khmer text
Reading with both heads: the decoder writes its 4 best guesses (beam search), the CTC draft is added, and
each guess is scored by both heads (0.5 Β· CTC + 0.5 Β· decoder). A guess that repeats or skips words gets a bad
CTC score; a guess with a missing vowel gets a bad decoder score.
Confidence: agreement of the two heads Γ how sure the CTC columns are. Use it to decide which lines a person
(or a bigger model) should check.
Vocabulary: 3,402 tokens (Khmer clusters + Latin, digits, punctuation; rare clusters fall back to single characters, so any text can be written).
Use it
pip install torch pillow safetensors huggingface_hub rapidfuzz
from huggingface_hub import snapshot_download
import sys
folder = snapshot_download("INGMUYLEANG/chakkhu-ocr")
sys.path.insert(0, folder)
from chakkhu import load, read
model, tok = load(folder) # CPU; load(folder, device="cuda") for a GPU
print(read(model, tok, ["line.png"])) # one picture = one text line
print(read(model, tok, ["line.png"], confidence=True)) # [("β¦", 0.98)]
# read(..., beam=0) β faster, CTC head only
Whole pages: the demo has a line finder, and a free API:
from gradio_client import Client, handle_file
c = Client("INGMUYLEANG/chakkhu-demo")
c.predict(handle_file("page.jpg"), "page", api_name="/read")
# β {"text": β¦, "lines": [{"text", "confidence", "box": [x, y, w, h]}], "ms": β¦}
Training
About 5 hours on one GPU in total (two runs: from scratch, then a 1-hour continuation with old-document data).
- Lines drawn by us (about half): Khmer sentences from the Akkhara project and from Khmer Wikipedia (CC BY-SA 4.0), English words, numbers, prices, dates; 35 open fonts; 9 picture styles: document, scan, Messenger-compressed, screenshot, photo, night, tiny blurry print, old print (ink bleed, worn type, patchy ink, yellow paper, show-through from the back of the page) and typewriter (each cluster struck separately: baseline bounce, uneven ribbon ink)
- Chanrith123333/khmer_english_ocr_image_line (CC BY 4.0)
- SoyVitou/62k-images-khmer-printed-dataset (MIT)
- Sokheng/khmer-synthetic-ocr-v1-100k (CC BY 4.0)
- Thareah/khmer-handwriting (MIT): real handwritten lines
- 2,228 lines from 89 scanned pages of Cambodian laws and royal decrees, 1993β2003 (Open Development Cambodia), read by Gemini and kept where it agreed with Chakkhu. Laws, decrees and official texts are not protected by copyright in Cambodia (Law on Copyright and Related Rights, 2003, Article 10).
- Fonts: Google Fonts, SIL Open Font License 1.1
- Loss: 0.3 Β· CTC + 0.7 Β· cross-entropy; AdamW, bf16, batch 96
- Test data never used for training: KHOB (MIT), 12 held-out decree pages
Thanks to the authors of these open datasets and fonts, Wikipedia contributors, Open Development Cambodia, and the KHOB benchmark authors.
License
Model weights and code: Apache-2.0. Please credit Ing Muyleang (Chakkhu).
- Downloads last month
- 2


