V2 Changes vs V1: - Commercial-clear license policy (MIT, CC BY 4.0, Bitstream, OFL only) - Handwriting separated from printed (no mixing) - License plates excluded (separate domain) - Group-based splits: font-group (printed), writer-group (handwriting) - EasyOCR/VNCV for audit only (not legitimizing sources) - Font safety verified: DejaVu full Vietnamese glyph coverage Models: - Printed V2: CER 0.88%, exact match 81.6% (epoch 10) - Handwriting V2: CER 15.16% (epoch 15, writer-group split) Datasets: - Printed V2: 10,000 samples (MIT text corpus + DejaVu fonts) - Handwriting V2: 2,790 samples (UIT_HWDB CC BY 4.0, 102 writers) Artifacts: - Schema files (labels.txt, splits.json, groups.json, char_dict.json, MANIFEST.json) - Evaluations + bucket evaluation + inference test - License audit + V2 release report - Scripts: build, export ONNX, bucket eval, inference test - Checkpoint download manifest (binaries on Kaggle + Gitea Release) Registries updated: - dataset_registry.yaml: viocr-printed-v2, viocr-handwriting-v2 - model_registry.yaml: V2 models with metrics + Kaggle kernel refs Kaggle assets: - Datasets: ngocthanhdoan/viocr-printed-v2, viocr-handwriting-v2 - Kernels: ngocthanhdoan/viocr-train-printed-v2, viocr-train-handwriting-v2 Generated by Z.ai Super Z (Devhub Solutions) on 2026-08-30
viocr
viocr is an independently engineered, Vietnamese-first OCR project designed around a CPU-first and multi-language-ready architecture. This repository is currently in Phase 1: document OCR contracts, public-source provenance, and optional backend integration. It does not claim that a production OCR model, KIE model, ONNX export, accuracy benchmark, or CPU latency target has been achieved yet.
Current status
The project includes a model-agnostic OCR result contract, Unicode-aware language-pack loading, provenance registries, a deterministic synthetic fixture, leakage checks, transparent OCR metrics, and a public-PDF ingestion pipeline. The document increment adds quadrilateral geometry, rotation normalization, layout/text detection contracts, a PaddleOCR adapter, a spaCy NER adapter, PaddleOCR KIE annotation conversion, and an own-model spaCy NER trainer. The existing recognition training prototype remains under src/rec/train.py; it is an experimental training script and is not yet the public inference API.
| Capability | Status |
|---|---|
| Vietnamese Unicode NFC normalization | Implemented and tested |
| External language packs | Implemented for vi and en |
| OCR result contract | Implemented |
| Dataset labels validator | Implemented: hashes, split coverage, duplicate/group leakage |
| Synthetic fixture | Implemented for smoke-test scope only; multi-font and capture augmentation are opt-in |
| Document pipeline contract | Implemented and tested: layout → detect → rotate → recognize → NER/KIE |
| Quadrilateral rotation/deskew | Implemented for line crops; synthetic perspective augmentation is available, document rectification remains backend-specific |
| PaddleOCR integration | Optional adapter; source code Apache-2.0, checkpoints require separate audit |
| spaCy Vietnamese NER | Optional framework adapter plus project-owned trainer; no third-party model auto-download |
| Detection model | Adapter contract only; production model not bundled |
| Production recognition model | Not implemented |
| ONNX export/inference | Planned; not benchmarked |
| CPU benchmark | Planned; not benchmarked |
| Dataset approval | Chinhphu PDFs are public-download research-only until document-level review |
| Model release | Blocked until legal and benchmark gates pass |
Quick start
The core package uses Python standard library components only for its initial smoke tests. From the repository root:
python -m unittest discover -s tests -v
PYTHONPATH=src python -m viocr vocab --lang vi
PYTHONPATH=src python -m viocr normalize 'ành phố'
# Original clean smoke fixture (24 images, one selected local font)
python tools/generate_fixture.py --output data/dataset/rec/vi/v_0 --font /usr/share/fonts/truetype/dejavu/DejaVuSans.ttf --overwrite
# Optional multi-font + capture-condition fixture (clean and augmented variants)
pip install -e '.[augment]'
PYTHONPATH=src python tools/generate_fixture.py --output /tmp/viocr-fixture-v2 --recommended-fonts --augment --variants 2 --overwrite
python tools/validate_dataset.py --help
python tools/smoke_baseline.py
pip install -e '.[extract]' # optional; downloads no models by itself
python tools/extract_weak_labels.py --help
python tools/promote_weak_labels.py --help
pip install -e '.[document,ner]' # optional PaddleOCR/spaCy stages
python tools/chinhphu_pdf_pipeline.py --help
python tools/pdf_textline_dataset.py --help
python tools/build_kie_annotations.py --help
python tools/train_spacy_ner.py --help
python tools/viocr_pipeline.py --help
Pipeline end-to-end image/PDF → vncv/EasyOCR weak labels → consensus gate → line crops → balanced/font-safe dataset → local/Kaggle training → ONNX → predict is documented in docs/OCR-PIPELINE.md. Environment-specific installation is in docs/INSTALLATION.md, and the opt-in GitHub–Kaggle daily training design is in docs/GITHUB-KAGGLE-CICD.md.
The fixture and smoke test do not download external data or require a model. The smoke output labelled oracle_metric_plumbing verifies only vocabulary/metric plumbing; it is not model accuracy. The generator records per-sample font_family, font_sha256, capture_condition, and augmentation seed in sample_metadata.jsonl; font provenance is documented in data/fonts/FONTS.md. To compare predictions by condition, pass the prediction TSV and metadata JSONL to tools/evaluate_ocr.py --metadata ... --group-by capture_condition --group-by font_family. Optional real-image extraction through vncv/EasyOCR is documented in docs/EXTRACTOR-INTEGRATION.md; model downloads require an explicit flag and weak labels require cross-engine consensus before promotion.
The training prototype has additional dependencies. Install them only when training work is explicitly started:
pip install -e '.[train]'
python src/rec/train.py --help
Data policy
Raw images, personal data, credentials, model checkpoints, and unverified third-party datasets must not be committed. Dataset use is gated by datasets/DATASET_MANIFEST.yaml, dataset_registry.yaml, and the reports in docs/. An unknown license or unknown privacy status means approved_for_training: false.
Architecture direction
The intended pipeline is:
image/PDF -> page orientation -> layout detection -> text detection
-> quadrilateral rotate/deskew -> recognition
-> NFC normalization -> reading order -> spaCy NER/KIE
-> provenance/quality gates -> DocumentOCRResult
Language-specific alphabets live in src/rec/langs/<lang>/<lang>.json; the core package does not hard-code Vietnamese as its only alphabet. PaddleOCR KIE conversion follows the documented transcription, label, points, id, and linking contract. See docs/research/PIPELINE-ARCHITECTURE-RESEARCH.md, docs/EXTRACTOR-INTEGRATION.md, docs/legal/, and 12-ROADMAP.md for boundaries and license gates.
Research and legal status
The Phase 0 reports are deliberately conservative. A public dataset is not automatically open, commercially usable, or redistributable. Claims about dataset size, license, privacy, or benchmark quality are recorded with a source and a verification status. No accuracy number in this repository should be read as a viocr result unless it is accompanied by a reproducible benchmark artifact.
License
The source code is provisionally released under Apache-2.0; see LICENSE, NOTICE, and docs/legal/LICENSE-COMPATIBILITY.md. The license choice does not grant rights to third-party datasets, fonts, pretrained weights, or external model artifacts.