xattot / README.md
otabektorayev's picture
Commercial contact email; absolute links to LICENSE and NOTICE
db5a5f1 verified
|
Raw History Blame Contribute Delete
15.6 kB
metadata
license: cc-by-nc-sa-4.0
language:
  - uz
  - ru
  - en
pipeline_tag: image-to-text
library_name: onnx
tags:
  - ocr
  - document-ai
  - uzbek
  - cyrillic
  - ctc
  - onnx

Steppe Labs

Xattot v1

Xattot turns images of printed documents (book scans, articles, theses, phone photos of pages) into Markdown text. It reads Uzbek (Latin and Cyrillic script), Russian and English, runs on a CPU with onnxruntime only, and is the first model released by Steppe Labs.

At its core is Satr, a small text-line recognizer (3.25M parameters) that Steppe Labs designed and trained from scratch. Satr is aimed at Uzbek Cyrillic text, where the Cyrillic letters Ò³ Ò› Ò“ Ñž are often misread by general OCR systems and vision-language models.

Xattot (Uzbek: "calligrapher, scribe"), the person who copied books by hand. Satr means "line".

Xattot benchmark

In our independent benchmark (details below):

  • On Uzbek Cyrillic book scans Xattot has the lowest error of the six systems tested: CER 0.61% against 1.75% for the next best (Qianfan-OCR). The difference is statistically significant.
  • It reads the letters Ò³ Ò› Ò“ Ñž correctly 98.6% of the time on book scans and 99.7% on printed pages. The vision-language models tested reach 49–73%, and Indra 33–34%.
  • On printed pages (scanner + phone camera) Xattot has the lowest error overall: 0.62% against 1.35% for PaddleOCR-VL-1.6. The difference is significant.
  • On Uzbek Latin, Russian and English book scans the difference to the best system is not significant. On Russian and English, PaddleOCR-VL-1.6 is numerically ahead (0.59% vs 1.16% and 0.16% vs 0.49%).
  • It runs on a CPU: about 1 s per text block and 7 s per page with 2 threads, while the vision-language models take 58–165 s per page on an NVIDIA T4 GPU.

Quick start

git clone https://huggingface.co/steppelabs/xattot && cd xattot
pip install -r requirements.txt
python xattot.py assets/sample_page.png --out result --draw     # result/sample_page.md, result/sample_page_boxes.jpg
from xattot import load_xattot, read_page

x = load_xattot()                     # first call downloads the Apache-2.0 layout/line models (~150 MB)
print(read_page(x, "page.jpg"))       # Markdown

Images are EXIF-rotated and scaled so that the longest side is at most 2,500 px, the same preparation as in the benchmark. --gpu uses onnxruntime-gpu.

How it works

step model source
page orientation (0/90/180/270°) PP-LCNet_x1_0_doc_ori PaddlePaddle, Apache-2.0
layout blocks and reading order PP-DocLayoutV3 PaddlePaddle, Apache-2.0
text lines in each block PP-OCRv5 mobile det PaddlePaddle, Apache-2.0
line image → text Satr v1 Steppe Labs, this repository
table structure → Markdown table (cells read by Satr) SLANet_plus PaddlePaddle, Apache-2.0
formula → LaTeX (optional, --formula, experimental) PP-FormulaNet_plus-L PaddlePaddle, Apache-2.0

PaddlePaddle is Baidu's open-source deep-learning platform. Xattot uses its released models in ONNX form, so the Paddle framework itself is not needed. These models are not included here: xattot.py downloads them from the official PaddlePaddle repositories at pinned revisions (see NOTICE). The pinned files are byte-identical (SHA-256) to the copies Xattot was developed and benchmarked with.

Satr v1: a CNN (line height 48 px → 1, width / 4) followed by 2 Transformer blocks (d=192, 4 heads) and a CTC head. It has 263 output characters: Latin, Cyrillic including ҳ қ ғ ў, Greek, digits, and sub/superscript and technical symbols. Two formats are included:

  • satr/satr.onnx for inference;
  • satr/satr.safetensors with satr_model.py for fine-tuning in PyTorch. Both give the same output.

Examples

Real Xattot output on pages from the benchmark. The boxes are drawn from Xattot's own output with no edits. The CER under each image is that of the output shown.

Phone photo, Uzbek Cyrillic, two columns

Scan, Uzbek Latin, two columns

Phone photo, Uzbek Cyrillic, 9 pt

The examples also show mistakes. On the first page the two-line title is split into three blocks, so the word "ва" lands after the second title line. On the second page a speck in the right margin is read as %.

Evaluation

The full protocol was written down before any system was run, including the decision rule below. All systems got the same images.

Systems:

system version hardware
Xattot v1 this repository CPU, 2 threads
PaddleOCR-VL-1.6 PaddlePaddle/PaddleOCR-VL-1.6 @ c5630ab, prompt OCR: per layout block, fp16 T4 GPU
Qianfan-OCR baidu/Qianfan-OCR @ 623bf5d, Parse this document to Markdown., fp16 T4 GPU
Unlimited-OCR baidu/Unlimited-OCR (v1) @ 8249d20, its own document prompt, bf16 T4 GPU
Tesseract 5.3.4, given the correct language (uzb, uzb_cyrl, rus, eng) CPU
Indra 1.1.2, default settings CPU, 2 threads

No paid APIs were tested.

Test sets:

  • Book scans: 99 text blocks. 104 blocks of 3–12 lines (586 lines in total) were drawn at random, with a fixed seed, one from each of 104 documents that were not used in training. They come from four groups: Uzbek Latin, Uzbek Cyrillic, Russian and English.
    • Reference text: a Steppe Labs annotator corrected each block against the image. The starting draft for each block came from one of the six systems, assigned at random and hidden from the annotator.
    • Scoring: each system is scored only on blocks it did not draft. Pairwise differences use blocks drafted by neither system.
    • On about 8 blocks an AI assistant pointed out possible errors; the annotator decided the final text from the image.
    • 5 blocks were excluded, leaving 99: 3 contained formulas, and in 2 a line was cut in half by the block border.
  • Printed pages: 10 pages that we typeset in fonts not used to train Satr: PT Serif/Sans/Mono, Linux Libertine, IBM Plex, Carlito and Computer Modern.
    • Layouts: one and two columns, typewriter style, and a 9 pt page.
    • Languages: Uzbek Latin 3, Uzbek Cyrillic 4, Russian 2, English 1.
    • Each page was printed, scanned at 300 dpi and photographed with a phone, giving 20 images.
    • The reference is the typeset text.

Metric and normalization:

  • Metric: character error rate (CER), micro-averaged, with 95% confidence intervals from a cluster bootstrap (10,000 resamples, clustered by block or by page).
  • The same normalization is applied to every system before scoring:
    • Unicode NFC;
    • one apostrophe, dash and quote form;
    • markup, tags and coordinates removed;
    • hyphens between letters dropped;
    • sub/superscripts flattened;
    • whitespace collapsed.
  • Upper/lower case and Latin–Cyrillic look-alikes count as errors.

Decision rule: "Xattot is best" is claimed only when the 95% interval of Xattot − best other system lies entirely below zero. If the interval lies above zero, Xattot is worse and this is listed as a limitation. Groups with fewer than 3 pages get no verdict.

Book scans (CER %, 95% CI)

group blocks Xattot PaddleOCR-VL-1.6 Qianfan-OCR Unlimited-OCR Tesseract 5 Indra Xattot − best other verdict
Uzbek Cyrillic 26 0.61 [0.3–1.1] 3.27 [2.3–4.8] 1.75 [1.1–2.6] 8.37 [2.8–17.2] 3.61 [0.4–10.2] 3.32 [2.8–3.8] −1.06 [−1.9…−0.2] (Qianfan) Xattot best
Uzbek Latin 26 0.42 [0.2–0.7] 0.67 [0.3–1.2] 0.64 [0.2–1.4] 0.37 [0.2–0.6] 1.15 [0.6–1.8] 1.04 [0.2–2.1] +0.11 [−0.2…+0.5] (Unlimited) not significant
Russian 23 1.16 [0.6–1.8] 0.59 [0.2–1.1] 0.86 [0.1–2.2] 0.81 [0.2–1.6] 2.19 [1.0–3.6] 1.50 [0.6–2.8] +0.34 [−0.1…+0.9] (PaddleOCR-VL) not significant
English 24 0.49 [0.0–1.2] 0.16 [0.0–0.3] 0.23 [0.1–0.4] 0.21 [0.1–0.4] 1.36 [0.3–3.3] 0.64 [0.0–2.1] +0.47 [−0.1…+1.5] (PaddleOCR-VL) not significant
All 99 0.64 [0.4–0.9] 1.11 [0.8–1.6] 0.86 [0.6–1.3] 2.62 [1.0–5.0] 2.07 [0.9–3.9] 1.58 [1.1–2.1] −0.20 [−0.7…+0.3] (Qianfan) not significant

Printed pages (CER %, 95% CI; bootstrap by page)

group images Xattot PaddleOCR-VL-1.6 Qianfan-OCR Unlimited-OCR Tesseract 5 Indra Xattot − best other verdict
scanner, Uzbek Latin 3 0.11 [0.1–0.1] 0.27 [0.2–0.3] 0.46 [0.1–0.7] 0.45 [0.1–0.6] 0.24 [0.1–0.5] 0.01 [0.0–0.0] +0.10 [+0.1…+0.1] (Indra) Xattot worse
scanner, Uzbek Cyrillic 4 1.10 [0.4–1.4] 2.56 [1.9–3.2] 26.07 [3.9–63.6] 15.99 [2.9–36.4] 1.22 [0.3–2.1] 26.73 [3.5–67.4] −0.13 [−1.0…+0.4] (Tesseract) not significant
camera, Uzbek Latin 3 0.02 [0.0–0.1] 0.27 [0.2–0.3] 0.19 [0.1–0.2] 0.35 [0.0–0.5] 22.29 [10.8–38.0] 0.20 [0.0–0.8] −0.16 [−0.2…−0.0] (Qianfan) Xattot best
camera, Uzbek Cyrillic 4 0.31 [0.0–0.6] 2.21 [1.4–3.4] 3.20 [2.3–4.2] 18.40 [2.8–45.9] 6.69 [4.4–8.9] 3.56 [3.2–4.4] −1.90 [−2.8…−1.2] (PaddleOCR-VL) Xattot best
scanner, all 10 0.79 [0.3–1.2] 1.48 [0.7–2.3] 10.77 [0.7–29.5] 6.63 [0.5–17.2] 0.87 [0.3–1.5] 10.97 [0.5–30.6] −0.08 [−0.6…+0.4] (Tesseract) not significant
camera, all 10 0.45 [0.1–0.8] 1.22 [0.5–2.1] 1.37 [0.4–2.5] 7.55 [0.4–21.5] 11.81 [7.4–17.2] 6.53 [0.9–17.0] −0.77 [−1.8…+0.2] (PaddleOCR-VL) not significant
all 20 0.62 [0.3–0.9] 1.35 [0.6–2.2] 6.07 [0.5–15.8] 7.09 [0.5–19.2] 6.34 [4.2–8.9] 8.75 [0.9–18.9] −0.73 [−1.4…−0.1] (PaddleOCR-VL) Xattot best

Russian (2 pages) and English (1 page) have too few pages for a verdict:

group Xattot PaddleOCR-VL-1.6 Qianfan-OCR Unlimited-OCR Tesseract 5 Indra
scanner, Russian 1.54 1.87 0.52 0.23 1.58 0.80
camera, Russian 0.66 1.28 0.12 0.03 6.64 25.54
scanner, English 0.14 0.00 0.00 0.00 0.03 0.00
camera, English 1.51 0.03 0.00 0.03 13.50 0.14

The other systems' large errors on printed pages come mostly from a few failed pages. Indra mixes up the column order on two-column pages. Qianfan-OCR and Unlimited-OCR repeat or drop text on one two-column page. Tesseract misses parts of the photographed pages.

Cyrillic letters Ò³ Ò› Ò“ Ñž

This is the share of these letters in the reference text that each system read correctly, measured on Uzbek Cyrillic text only.

set Xattot PaddleOCR-VL-1.6 Qianfan-OCR Unlimited-OCR Tesseract 5 Indra
book scans (26 blocks) 98.6% 57.0% 68.8% 48.9% 95.2% 32.8%
printed pages (8 images) 99.7% 73.1% 52.9% 51.9% 95.5% 33.8%

Speed (mean seconds; for information, not part of the decision)

Xattot PaddleOCR-VL-1.6 Qianfan-OCR Unlimited-OCR Tesseract 5 Indra
hardware CPU, 2 threads T4 GPU T4 GPU T4 GPU CPU CPU, 2 threads
per text block 0.97 8.97 13.45 6.24 1.05 0.29
per page 7.1 103 165 58 7.5 1.3

Notes on the run:

  • PaddleOCR-VL on printed pages. On two printed pages our harness gave PaddleOCR-VL-1.6 overlapping layout boxes, so it read the same text twice. That harness bug was ours, not the model's. We fixed it (a box is dropped when 90% of its ink lies inside smaller boxes) and re-ran PaddleOCR-VL on the printed pages. The tables show that second run; only those two pages changed.
  • Small differences across machines. Xattot's output can differ slightly between machines because onnxruntime uses different floating-point kernels on different CPUs. The third example page measures 0.26% CER here and 0.24% in the benchmark run.

Limitations

  • Printed text only. Handwriting is not supported, and neither is Arabic script (old Uzbek, Chagatai and Ottoman texts).
  • Uzbek Latin apostrophe letters are written with the ASCII apostrophe (o', g'), not Ê».
  • Russian and English: large vision-language models are numerically better on our book scans. The difference is not significant.
  • Scanned Uzbek Latin pages: Indra is better (0.01% vs 0.11% CER).
  • Reading order can break on multi-line headings and complex layouts; see the first example.
  • Formulas and tables:
    • Formula blocks were excluded from the benchmark.
    • The --formula module is experimental. On a small internal check, 60% of formulas were fully correct.
    • Table recognition was not part of this benchmark.
  • Benchmark size: 99 blocks and 20 images. The confidence intervals are wide for small groups.

Training

Satr was trained from scratch by Steppe Labs on printed text lines in Uzbek (Latin and Cyrillic), Russian and English: about 443K real line images, plus synthetic lines rendered on the fly that make up 35% of training samples. The training data sources are not disclosed. No benchmark document was used in training. The layout, line, orientation, table and formula models are PaddlePaddle's released models, used unchanged.

License

  • Satr weights, Xattot code and figures: CC BY-NC-SA 4.0 (full text in LICENSE).
    • Allowed: non-commercial use, research and fine-tuning.
    • Fine-tuned weights may be shared under the same license, with credit to Xattot and Steppe Labs.
    • Commercial use needs permission from Steppe Labs: write to steppelabsai@gmail.com. Questions and bug reports: the Community tab of this repository.
  • PaddlePaddle models that Xattot downloads keep their own license, Apache-2.0 (see NOTICE).
  • Your output: Steppe Labs claims no rights over the text you extract with Xattot.

Citation

@misc{steppelabs2026xattot,
  title        = {Xattot: CPU document OCR for Uzbek (Latin and Cyrillic), Russian and English},
  author       = {{Steppe Labs}},
  year         = {2026},
  howpublished = {\url{https://huggingface.co/steppelabs/xattot}}
}

Oʻzbekcha qisqacha

Xattot — bosma hujjat rasmidan (kitob skani, maqola, dissertatsiya, telefonda olingan varaq) Markdown matn oladigan OCR tizimi. U oʻzbek (lotin va kirill), rus va ingliz tillarini oʻqiydi va oddiy kompyuter protsessorida (CPU) ishlaydi.

Ichidagi Satr qator modelini Steppe Labs noldan oʻqitgan.

Mustaqil sinovimizda:

  • oÊ»zbek kirill kitob skanlarida xato 0.61%. Bu sinalgan 6 tizimning eng yaxshisi, farq statistik jihatdan ishonchli;
  • Ò³ Ò› Ò“ Ñž harflarining 98.6–99.7% ini toÊ»gÊ»ri oÊ»qiydi;
  • oÊ»zbek lotin, rus va ingliz matnida eng yaxshi tizimlar bilan farq aniqlanmadi.

Litsenziya CC BY-NC-SA 4.0: notijoriy foydalanish va fine-tune mumkin. Tijoriy foydalanish uchun: steppelabsai@gmail.com.