# OAR-OCR
[](https://crates.io/crates/oar-ocr)

[](https://deps.rs/repo/github/GreatV/oar-ocr)

A native Rust toolkit for OCR, document layout analysis, and vision-language document understanding.
## Highlights
- End-to-end text detection and recognition with PP-OCR models, including PP-OCRv6.
- Document structure analysis for layout, tables, formulas, seals, orientation, and rectification.
- Native Candle inference for compact document VLMs through the `oar-ocr-vl` crate.
- CPU and GPU execution, model auto-download, and in-memory ONNX model loading.
- Any supported VLM loads by its Hugging Face model ID and downloads on first use.
- One documented [page JSON format](docs/page-format.md) from both the classic and vision-language pipelines.
- The `oar` command-line tool for OCR, structure analysis, and VLM parsing of images and PDFs.
## Quick Start
### Command line
Install the standalone tool with `cargo install oar-ocr-cli` (or add `--features cuda`). Inputs can be images or PDFs. Models download automatically; `auto` selects an available compiled device.
```bash
oar ocr page.png
oar indra page.png --device cpu
oar structure page.png -o documents
oar parse --model PaddlePaddle/PaddleOCR-VL-1.5 page.png
oar structure report.pdf --pages 1-3 --format json
```
See the [CLI guide](https://github.com/GreatV/oar-ocr/blob/main/oar-ocr-cli/README.md) for JSON output, model overrides, and local checkpoints.
### Installation
```bash
cargo add oar-ocr
```
The default build enables ONNX Runtime binary downloads and SIMD acceleration. Add only the optional capabilities needed by your application. For example:
```bash
cargo add oar-ocr --features cuda,auto-download
```
This keeps the default `download-binaries` and `simd` features enabled, makes the ONNX Runtime CUDA execution provider available for selection, and downloads missing registered model files from ModelScope into `$OAR_HOME` when they are first used.
See the [Cargo feature guide](docs/features.md) for all available features and the [model guide](docs/models.md#auto-download) for model download and cache behavior.
Builders also accept raw ONNX bytes such as `include_bytes!`, allowing models to be embedded in a single binary. See [Loading Models from Memory](docs/usage.md#loading-models-from-memory).
### OCR Pipeline
The `pp_ocrv6` preset configures a PP-OCRv6 pipeline by model size, filling in the model names, the matching dictionary, and the official detection thresholds. With `auto-download`, the names resolve through the model registry; without it they resolve as local paths, so nothing changes for offline setups.
```rust
use oar_ocr::prelude::*;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let ocr = OAROCRBuilder::pp_ocrv6(PpOcrV6Size::Small).build()?;
let image = load_image(Path::new("document.jpg"))?;
let results = ocr.predict(vec![image])?;
for region in &results[0].text_regions {
if let Some((text, confidence)) = region.text_with_confidence() {
println!("{text} ({confidence:.2})");
}
}
Ok(())
}
```
The preset's detection thresholds are defaults, so a `text_type` like `seal` still applies its own detection settings, and an explicit `text_detection_config` overrides everything. Sizes pick the models, the dictionary, and PaddleOCR's per-size box threshold (0.4 for Tiny, 0.45 for Small and Medium): `PpOcrV6Size::Tiny` runs the fastest pair over its reduced dictionary.
```rust
use oar_ocr::prelude::*;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let ocr = OAROCRBuilder::pp_ocrv6(PpOcrV6Size::Tiny).build()?;
let image = load_image(Path::new("document.jpg"))?;
let results = ocr.predict(vec![image])?;
for region in &results[0].text_regions {
if let Some((text, confidence)) = region.text_with_confidence() {
println!("{text} ({confidence:.2})");
}
}
Ok(())
}
```
### Document Structure Analysis
The `pp_structurev3` preset configures the PP-StructureV3-style stack: PP-DocLayoutV3 layout, PP-OCRv6 Tiny text recognition, table classification, SLANeXt wired and SLANet+ wireless table structure, wired cell detection, and the table dictionary.
```rust
use oar_ocr::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let structure = OARStructureBuilder::pp_structurev3().build()?;
let result = structure.predict("document.jpg")?;
println!("{}", result.to_markdown());
Ok(())
}
```
The exact chain the preset expands to, for swapping individual models:
```rust
use oar_ocr::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let structure = OARStructureBuilder::new("pp-doclayoutv3.onnx")
.layout_model_name("PP-DocLayoutV3")
.with_ocr(
"pp-ocrv6_tiny_det.onnx",
"pp-ocrv6_tiny_rec.onnx",
"ppocrv6_tiny_dict.txt",
)
.with_table_classification("pp-lcnet_x1_0_table_cls.onnx")
.with_wired_table_structure("slanext_wired.onnx")
.with_wireless_table_structure("slanet_plus.onnx")
.with_wired_table_cell_detection("rt-detr-l_wired_table_cell_det.onnx")
.table_structure_dict_path("table_structure_dict_ch.txt")
.build()?;
let result = structure.predict("document.jpg")?;
println!("{}", result.to_markdown());
Ok(())
}
```
### Vision-Language Page Parsing
With `cargo add oar-ocr-vl --features auto-download` (plus `cargo add image` for decoding), any supported VLM loads by its Hugging Face model ID; the checkpoint downloads from ModelScope (or Hugging Face) on first use and is cached under `~/.oar`.
```rust
use oar_ocr_vl::{
AnyPageParser, AnyPageParserModel, AnyPageParserOptions, AnyPageParserPretrainedOptions,
PageParser, auto_device,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let parser = AnyPageParser::from_pretrained(
AnyPageParserModel::PaddleOcrVl1_5,
auto_device(),
&AnyPageParserPretrainedOptions::default(),
)?;
let image = image::open("document.jpg")?.to_rgb8();
let page = parser.parse_page(&image, &AnyPageParserOptions::default())?;
println!("{}", page.markdown.unwrap_or_default());
Ok(())
}
```
Both pipelines export the same [page JSON](docs/page-format.md): `page.to_json(width, height)` here, and `StructureResult::to_json(width, height)` for the classic structure pipeline.
## Supported Models
The classic pipeline runs ONNX models through ONNX Runtime and supports the following model families. See the [pre-trained model guide](docs/models.md) for exact checkpoints, dictionaries, download links, and auto-download names.
### Classic ONNX Models
| Text detection | PP-OCRv4, PP-OCRv5, and PP-OCRv6 DB detectors |
| Text recognition | PP-OCRv3, PP-OCRv4, PP-OCRv5, PP-OCRv6, SVTRv2, and RepSVTR CTC recognizers |
| Document preprocessing | PP-LCNet document orientation, PP-LCNet text-line orientation, and UVDoc rectification |
| Layout detection | PicoDet, RT-DETR-H, PP-DocLayout S/M/L, PP-DocLayout Plus-L, PP-DocLayoutV2/V3, and PP-DocBlockLayout |
| Table analysis | PP-LCNet table classification, RT-DETR-L cell detection, and SLANet, SLANet+, and SLANeXt structure recognition |
| Formula recognition | PP-FormulaNet, PP-FormulaNet Plus, and UniMERNet |
| Seal text detection | PP-OCRv4 mobile and server seal detectors |
Available text-recognition checkpoints cover Chinese, Traditional Chinese, English, Arabic, Cyrillic, Devanagari, Greek, Eastern Slavic, Japanese, Georgian, Korean, Latin, Tamil, Telugu, and Thai scripts or languages.
[Indra OCR](https://huggingface.co/datalab-to/indra-ocr) runs as its own ONNX pipeline (`oar_ocr::indra`): small CPU-first models that read a page in 80+ languages into lines, layout blocks in reading order, and Markdown with HTML tables, with n-gram language models for unsure lines and optional inline LaTeX for math lines. See the [usage guide](docs/usage.md#indraocrbuilder---indra-ocr).
### Vision-Language Models
The [`oar-ocr-vl`](oar-ocr-vl/README.md) crate provides native [Candle](https://github.com/huggingface/candle) inference for compact document VLMs on CPU, CUDA, and Metal.
| [GLM-OCR](https://huggingface.co/zai-org/GLM-OCR) | 0.9B | Page parsing, text, table, and formula recognition |
| [HPD-Parsing](https://huggingface.co/PaddlePaddle/HPD-Parsing) | 1B | Hierarchical full-page parsing with continuously batched content branches, zero-copy shared-prefix KV, and per-branch P-MTP |
| [HunyuanOCR 1.5 / 1.0](https://huggingface.co/tencent/HunyuanOCR) | 1B | Prompt-driven full-page parsing, text spotting, table, formula, and chart recognition, with optional DFlash decoding for 1.5 |
| [jina-ocr-v1](https://huggingface.co/jinaai/jina-ocr-v1) | 3B (570M active) | End-to-end page-to-Markdown parsing (SAM+CLIP DeepEncoder over a DeepSeek-V2 MoE decoder) |
| [MinerU-Diffusion-V1-0320](https://huggingface.co/opendatalab/MinerU-Diffusion-V1-0320-2.5B) | 2.5B | Block-diffusion OCR with structured two-step extraction or single-pass text recognition |
| [MinerU2.5-2509](https://huggingface.co/opendatalab/MinerU2.5-2509-1.2B) | 1.2B | Model-native two-step layout detection and content extraction |
| [MinerU2.5-Pro-2605](https://huggingface.co/opendatalab/MinerU2.5-Pro-2605-1.2B) | 1.2B | Newer MinerU2.5 checkpoint using the same two-step pipeline |
| [MonkeyOCRv2-B-Parsing](https://huggingface.co/zenosai/MonkeyOCRv2-B-Parsing) | 0.7B | Higher-capacity ViT-B variant with the same parsing and recognition tasks |
| [MonkeyOCRv2-S-Parsing](https://huggingface.co/zenosai/MonkeyOCRv2-S-Parsing) | 0.6B | Model-native layout, end-to-end parsing, text, formula, and OTSL-table recognition |
| [OvisOCR2](https://huggingface.co/ATH-MaaS/OvisOCR2) | 0.8B | Model-native full-page document-to-Markdown parsing |
| [OvisOCR3](https://huggingface.co/ATH-MaaS/OvisOCR3) | 0.8B | Model-native Markdown or structured page parsing, text, formula, HTML table, and chart recognition |
| [OXR-1.0](https://huggingface.co/SoMarkAI/OXR-1.0) | 1.4B | PP-DocLayout page parsing and text, formula, HTML table, code, and chemical-structure recognition |
| [PaddleOCR-VL](https://huggingface.co/PaddlePaddle/PaddleOCR-VL) | 0.9B | Page parsing, text, table, formula, and chart recognition |
| [PaddleOCR-VL-1.5](https://huggingface.co/PaddlePaddle/PaddleOCR-VL-1.5) | 0.9B | PaddleOCR-VL tasks plus text spotting and seal recognition |
| [PaddleOCR-VL-1.6](https://huggingface.co/PaddlePaddle/PaddleOCR-VL-1.6) | 0.9B | Region-aware page parsing and task-specific recognition |
| [TeleOCR](https://huggingface.co/XingChen-AGI/TeleOCR) | 1.2B | Text, table (OTSL), formula, code, and layout recognition for digital and camera-captured documents (formerly NaviDC-OCR) |
| [WeVisDoc-2B](https://huggingface.co/tencent/WeVisDoc-2B) / [4B](https://huggingface.co/tencent/WeVisDoc-4B) | 2B / 4B | Model-native full-page document-to-Markdown parsing (Qwen3-VL with DeepStack) |
| [Xiaomi-OCR-0](https://huggingface.co/SeerRay-Lab/Xiaomi-OCR-0) | 0.8B | Model-native full-page document-to-Markdown parsing (Qwen3.5; tables as OTSL converted to HTML) |
| [Youtu-Parsing-Omni](https://huggingface.co/tencent/Youtu-Parsing-Omni) | 5B | Native image/document parsing to structured JSON, layout blocks, and Markdown (Youtu omni encoder and MLA decoder) |
PaddleOCR-VL variants, GLM-OCR, TeleOCR, OXR, jina-ocr-v1, and WeVisDoc integrate with the external-layout [`DocParser`](oar-ocr-vl/README.md#document-parsing-pipeline). OvisOCR2, OvisOCR3, WeVisDoc, Xiaomi-OCR-0, HPD-Parsing, Youtu-Parsing-Omni, and the MonkeyOCRv2 S/B parsing models also provide model-native full-page paths. HunyuanOCR and the MinerU models also use their model-native parsing pipelines.
OXR uses the explicit repository ID `SoMarkAI/OXR-1.0` through `AnyPageParser`. PP-DocLayout supplies its regions and reading order; the official separate D-FINE layout model is not used. See the [OXR guide](oar-ocr-vl/README.md#oxr-10) for weight-license terms, region tasks, and pixel controls.
See the [`oar-ocr-vl` guide](oar-ocr-vl/README.md) for setup and [`oar-ocr-vl/examples`](oar-ocr-vl/examples) for runnable examples.
## Documentation
- [Usage guide](docs/usage.md) — APIs, builder patterns, accelerators, and model loading
- [Page JSON format](docs/page-format.md) — the shared output schema of both pipelines
- [Benchmarking](docs/benchmarking.md) — reproducible pipeline baselines and comparisons
- [Cargo features](docs/features.md) — defaults, execution providers, and feature combinations
- [Pre-trained models](docs/models.md) — model files, dictionaries, and auto-download behavior
- [Environment variables](docs/environment-variables.md) — runtime and performance overrides
- [FAQ](docs/FAQ.md) — common build and runtime issues
## Examples
See the [usage guide](docs/usage.md) for other pipeline configurations and APIs. Complete classic-pipeline examples live in [`examples`](examples), while VLM examples live in [`oar-ocr-vl/examples`](oar-ocr-vl/examples).
## Acknowledgments
This project builds upon the excellent work of several open-source projects:
- **[ort](https://github.com/pykeio/ort)**: Rust bindings for ONNX Runtime by pykeio. This crate provides the Rust interface to ONNX Runtime that powers the efficient inference engine in this OCR library.
- **[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)**: Baidu's awesome multilingual OCR toolkits based on PaddlePaddle. This project utilizes PaddleOCR's pre-trained models, which provide excellent accuracy and performance for text detection and recognition across multiple languages.
- **[Candle](https://github.com/huggingface/candle)**: A minimalist ML framework for Rust by Hugging Face. We use Candle to implement Vision-Language model inference.