Repository navigation
FAQ
Generating synthetic OCR training data for mixed Khmer/English text. You give it a text corpus and fonts; it produces labelled line images with realistic degradation, optionally packed into LMDB for a training pipeline.
No. Generation is CPU-bound image work, parallelised across processes.
No. The Rust extension is an optional accelerator; every accelerated path has a pure-Python
fallback, so pip install ocr-foundry (or legacy khocr-gen) works anywhere.
No. The PyPI wheel is pure Python; HAS_RUST_ACCEL will be False unless you build from source
with the rust extra. The dev extra alone does not install native acceleration.
uv run python -c "from khocr_gen import _rust_accel as ra; print(ra.HAS_RUST_ACCEL)"Roughly filtered_lines × copies for train, plus one image per line for val and test (or one per
font per line with --font-mode all). Oversampled training lines add more. Don't guess — run:
khocr-gen generate --corpus corpus/corpus.txt --count-onlyDeliberate design. Stacking degradations compounds into unrealistic images and makes it impossible to attribute quality changes to a method. One effect per image, chosen by weighted probability, keeps the distribution controllable and the dataset interpretable.
Not through the built-in pipeline. Generate twice with different settings and merge with
khocr-gen combine if you want a wider distribution.
--text-deco-bold-prob and --text-deco-italic-prob use real variant fonts. If your font pool
has no file tagged bold (or italic/oblique), the decoration is skipped for that line rather than
faked. Add variant files to the pool. See Fonts.
Random text colour requires --color-mode 3 (RGB). In the default grayscale output there's no
colour to apply.
The RNG is reseeded per image so pure-Python methods reproduce across runs, but Rust-accelerated
methods keep their own thread RNG and still vary. Some variation in verify output is expected
and not a bug.
Yes, for generate: with fixed corpus bytes, fonts, configuration and software
versions, --seed (default 42) controls splitting and per-sample rendering,
decorations, variable heights and augmentation. Images, labels and metadata
are reproducible across worker counts. Seeded augmentation uses Python
implementations instead of native Rust; --seed none disables per-sample
seeding. Different fonts or runtimes may produce different bytes. The separate
verify preview command has its own RNG behavior described above.
See Corpus and Normalization.
Yes — that's --line-height-mode variable|bucketed. See Variable Line Height.
Downstream loaders must handle non-uniform image dimensions.
No. Images are rendered at their natural size and then uniformly resized to the sampled height (never cropped), so glyphs are never cut off. There are no retries or rejected samples.
--storage raw writes image files, lmdb packs and then deletes them, both keeps both. The
legacy --pack-lmdb / --keep-raw flags map onto the same behaviour.
The key layout is plain strings: image-000000001, label-000000001, and num-samples. Any LMDB
client can read it. See Output and Storage.
Yes — --image-dir DIR bypasses rendering and uses images you already have. The "corpus" must then
be a labels.txt in the standard format.
Yes. khocr-gen combine merges any mix of raw and LMDB splits and always emits LMDB, along with a
merged vocab.json.
If you set only one of --val-percent / --test-percent, the other becomes 0; that's the
documented behaviour. Use --split-ratios for explicit control. See
Corpus and Normalization.
Yes. Splits are disjoint at the text level, so no text string appears in two splits, and an augmented variant of a training line can never leak into val or test.
No. Oversampling applies to train only; val and test stay at one copy per line so evaluation
reflects the natural corpus distribution.
Almost certainly a nested mapping. The YAML loader only reads flat keys; a nested block is
dropped and the default is kept. Use sauvola-prob: 0.2 rather than sauvola: {prob: 0.2}.
Watch stderr for Config key 'sauvola' is a nested mapping; only flat keys are supported, skipping.
See Configuration.
Decorations (color, underline, sub/superscript, bold, italic) combine. Effects (shadow, glow, outline, …) are mutually exclusive: at most one per line, first probability hit wins. Both run before augmentation. See Text Decorations and Effects.
No. Every effect and decoration preserves the underlying glyph shapes; the rendered text remains the ground-truth OCR label.
distortion, albu_noise, gradient_illumination, extreme_resize, low_contrast_caption, and luminous_halo.
See Rust Acceleration for the reasons.
Pixel heights, not [0, 1] intensities; it's the only method like that. Defaults are 8 and
1920.
Yes. Dependencies use opencv-python-headless, so no GUI libraries are needed.
Yes — khocr-gen view --lmdb DIR --summary|--output-dir|--labels-only. For augmentation QA use
khocr-gen verify.
The package is importable (khocr_gen.rendering.ImageRenderer,
khocr_gen.data_generator.DatasetGenerator, khocr_gen.config.GenerationConfig), but the supported
interface is the CLI. See Architecture for the module map.
Open an issue at https://github.com/0x1d1e/ocr-foundry/issues. Include the exact command, the
config file if you used one, the observed output, and the khocr-gen --version value. If images
look wrong, attach a sample and the verify_output render for the method involved.
OCR Foundry — synthetic OCR training data with Khmer/English and opt-in multilingual rendering · MIT · Repository · Issues · PyPI · Changelog
Using OCR Foundry
Data controls
- Corpus and Normalization
- Fonts
- Variable Line Height
- Text Decorations and Effects
- Augmentation
- Output and Storage
- Page Layout
Internals
Help