oar-ocr
Library Listed
An Optical Character Recognition (OCR) and Document Layout Analysis library written in Rust.
- Downloads
- 34,387
- Dependents
- 9
- Stars
- 204
- Forks
- 35
- Contributors
- 11
- Commits
- 238
- Latest release
- 0.10.2 ·
About
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-vlcrate. - 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 from both the classic and vision-language pipelines.
- The
oarcommand-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.
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 for JSON output, model overrides, and local checkpoints.
Read the full README
Installation
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:
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 for all available features and the model guide 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.
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.
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.
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.
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:
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.
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: 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 for exact checkpoints, dictionaries, download links, and auto-download names.
Classic ONNX Models
| Task | Supported model families |
|---|---|
| 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 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.
Vision-Language Models
The oar-ocr-vl crate provides native Candle inference for compact document VLMs on CPU, CUDA, and Metal.
| Model | Parameters | Capabilities |
|---|---|---|
| GLM-OCR | 0.9B | Page parsing, text, table, and formula recognition |
| 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 | 1B | Prompt-driven full-page parsing, text spotting, table, formula, and chart recognition, with optional DFlash decoding for 1.5 |
| 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 | 2.5B | Block-diffusion OCR with structured two-step extraction or single-pass text recognition |
| MinerU2.5-2509 | 1.2B | Model-native two-step layout detection and content extraction |
| MinerU2.5-Pro-2605 | 1.2B | Newer MinerU2.5 checkpoint using the same two-step pipeline |
| MiniCPM-OCR 1.0 | 1.3B | PP-DocLayout page parsing and text, formula, OTSL table, chart, and seal recognition (SigLIP + Qwen3.5) |
| MonkeyOCRv2-B-Parsing | 0.7B | Higher-capacity ViT-B variant with the same parsing and recognition tasks |
| MonkeyOCRv2-S-Parsing | 0.6B | Two-stage page parsing, dewarp, layout, text, formula, and OTSL-table recognition |
| OvisOCR2 | 0.8B | Model-native full-page document-to-Markdown parsing |
| OvisOCR3 | 0.8B | Model-native Markdown or structured page parsing, text, formula, HTML table, and chart recognition |
| OXR-1.0 | 1.4B | PP-DocLayout page parsing and text, formula, HTML table, code, and chemical-structure recognition |
| PaddleOCR-VL | 0.9B | Page parsing, text, table, formula, and chart recognition |
| PaddleOCR-VL-1.5 | 0.9B | PaddleOCR-VL tasks plus text spotting and seal recognition |
| PaddleOCR-VL-1.6 | 0.9B | Region-aware page parsing and task-specific recognition |
| TeleOCR | 1.2B | Text, table (OTSL), formula, code, and layout recognition for digital and camera-captured documents (formerly NaviDC-OCR) |
| Unlimited-OCR-2 | 3B (570M active) | Single- and multi-page document-to-Markdown parsing (DeepEncoder over a DeepSeek-V2 MoE decoder with DASH block-sparse attention) |
| WeVisDoc-2B / 4B | 2B / 4B | Model-native full-page document-to-Markdown parsing (Qwen3-VL with DeepStack) |
| Xiaomi-OCR-0 | 0.8B | Model-native full-page document-to-Markdown parsing (Qwen3.5; tables as OTSL converted to HTML) |
| 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, MiniCPM-OCR, OXR, jina-ocr-v1, and WeVisDoc integrate with the external-layout DocParser. 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. Unlimited-OCR-2 parses whole pages, alone or several per request, through its model-native path only. HunyuanOCR and the MinerU models also use their model-native parsing pipelines.
PageParser::parse_document returns a DocumentOutput with pages and document Markdown. Unlimited-OCR-2 uses one joint request with tiled views by default; HunyuanOCR 1.5 and OvisOCR3 offer explicit joint-generation methods. See the page and document API guide.
MiniCPM-OCR uses the explicit repository ID openbmb/MiniCPM-OCR-1.0 through AnyPageParser and, like its official SDK, reads the regions PP-DocLayoutV3 detects; see the MiniCPM-OCR guide.
OXR uses the explicit repository ID SoMarkAI/OXR-1.0 through AnyPageParser. PP-DocLayout supplies regions, and OXR predicts their reading order with its grounding prompt by default. Oxr::with_reading_order(false) selects detector order. See the OXR guide for details and weight-license terms.
Chart-region recognition is opt-in through PaddleOcrVl::with_chart_recognition(true). GLM-OCR defaults to repetition penalty 1.1, and HunyuanOCR page parsing selects the loaded version's official prompt. See the VL usage guide for model defaults and controls.
See the oar-ocr-vl guide for setup and oar-ocr-vl/examples for runnable examples.
Documentation
- Usage guide — APIs, builder patterns, accelerators, and model loading
- Page JSON format — the shared output schema of both pipelines
- Benchmarking — reproducible pipeline baselines and comparisons
- Cargo features — defaults, execution providers, and feature combinations
- Pre-trained models — model files, dictionaries, and auto-download behavior
- Environment variables — runtime and performance overrides
- FAQ — common build and runtime issues
Examples
See the usage guide for other pipeline configurations and APIs. Complete classic-pipeline examples live in examples, while VLM examples live in oar-ocr-vl/examples.
Acknowledgments
This project builds upon the excellent work of several open-source projects:
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: 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: A minimalist ML framework for Rust by Hugging Face. We use Candle to implement Vision-Language model inference.
Compatibility
- Runs on
- CUDA, WebGPU, Metal
What shows it
- CUDA: oar-ocr feature cuda, oar-ocr-cli feature cuda, oar-ocr-core feature cuda, oar-ocr-vl feature cuda
- WebGPU: oar-ocr feature webgpu, oar-ocr-core feature webgpu
- Metal: oar-ocr-cli feature metal, oar-ocr-vl feature metal
- Native code
- Required
- Binds native code: ort-sys
- Python bindings
- No Python binding crate found
- License
- Apache-2.0
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days. ML Rust runs this catalogue, so its closest project always gets a row.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
An Optical Character Recognition (OCR) and Document Layout Analysis library written in Rust. |
34,387 downloads over 30 days | 9 | 204 | 0.10.2 | CUDA, WebGPU, Metal | Binds native code: ort-sys | Apache-2.0 |
|
Productive Rust binding for Tesseract and Leptonica. Also in Documents and OCR. |
16,918 downloads over 30 days | 14 | 286 | 0.14.0 | GPU support unknown | Binds native code: leptonica-sys, tesseract-sys | MIT |
|
rust-paddle-ocr Listed
A lightweight and efficient OCR library based on PaddleOCR models, using the MNN inference framework for high-performance text detection and recognition Also in Documents and OCR. |
2,742 downloads over 30 days | 5 | 346 | 2.4.1 | CUDA, Metal, Vulkan | Build uses a native toolchain: bindgen, cc, cmake | Apache-2.0 |
|
inference Listed
Ultralytics YOLO inference library and CLI for Rust Also in Run and serve models. |
2,609 downloads over 30 days | 1 | 217 | 0.0.56 | CUDA, WebGPU, ROCm | Binds native code: ort-sys, ffmpeg-sys-next (feature video), openvino-sys (feature intel) | AGPL-3.0 |
|
usls Listed
A Rust library integrated with ONNXRuntime, providing a collection of ML models. Also in Run and serve models. |
355 downloads over 30 days | 1 | 447 | 0.1.11 | CUDA, ROCm | Binds native code: ffmpeg-sys-next (feature video), ort-sys (feature acl) | MIT |
|
rusto-rs New
RustO! - Pure Rust OCR library based on RapidOCR with PaddleOCR engine Also in Documents and OCR. |
1,618 downloads over 30 days | 1 | 127 | 0.3.2 | CUDA, Metal, Vulkan | Binds native code: rusto-mnn-sys. Build uses a native toolchain: bindgen, cc, cmake | MIT |
|
Model conversion and quantization with no Python: reads SafeTensors, GGUF, TCF and PyTorch state dicts, writes SafeTensors, GGUF and TCF, and quantizes to Q2_K through Q8_0 and IQ4 formats, including Q4_K_M mixes. GPTQ, AWQ, NF4, FP8, EXL2 and ONNX input are not implemented. Python bindings Also in Run and serve models. |
23 downloads over 30 days | Not applicable | 0 | 0.2.1 | GPU support unknown | No native code found | Apache-2.0 |
All projects in Run and serve modelsAll projects in Documents and OCR
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- It has 8 active dependents and 8 new dependents in 365 days. Featured needs 11 active dependents or 9 new dependents in 365 days. The repository route reads 204 stars, 35 forks and 11 contributors. It needs 4,539 stars, 434 forks and 79 contributors together.
What else the check found
- The last activity is on 6 Nov 2026, 3 days ago. The rules expect an update within 365 days. Dormancy rule
Exact rules: Listed, Featured library. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: version 0.10.2 base 300, raised to the 365-day floor: E = 365 daysdormancy: last activity 2026-11-06, 3 days ago, E = 365: activefeatured: not featured: active_users 8 < 11 and new_adopters 8 < 9 and repository route stars 204 (needs 4539), forks 35 (needs 434), contributors 11 (needs 79)listed: listed: no archive, new or featured rule applies
Crates5 crates
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: the crates.io description
- crates.io database dump, fetched
- RustSec advisory database, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption8 active dependents, 8 new dependents in 365 days1 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | 8 | crates.io database dump | Yes | |
| New dependents (365 days) | 8 | crates.io database dump | Yes | |
| Peak active dependents | 7.5 | crates.io database dump | Yes | |
| Active dependents as a share of the peak | 1 | crates.io database dump | Yes | |
| Binary downloads per release | Not measured | Yes |
MaintenanceLatest human commit: 3 days ago3 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-11-06 | GitHub repository | Yes | |
| Latest release | 2026-10-26 | crates.io database dump | Yes | |
| First release | 2025-07-31 | crates.io database dump | Yes | |
| Latest version | 0.10.2 | crates.io database dump | Yes | |
| Days the oldest outside issue waits for a reply | 6 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 38 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | Yes | |
| Published docs | true | crates.io database dump | Yes | |
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityUnpatched vulnerabilities: none
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | none | RustSec advisory database | Yes | |
| RustSec unmaintained advisory | none | RustSec advisory database | Yes | |
| Deprecation notice | none | crates.io database dump | Yes | |
| Deprecated requirement | none | crates.io database dump | Yes |
Distribution28 releases, 34,387 downloads over 30 days5 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 28 | crates.io database dump | Yes | |
| Downloads over 30 days | 34387 | crates.io database dump | Yes | |
| Binary downloads over the last 3 releases | Not measured | Yes | ||
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | false | crates.io database dump | Yes | |
| Crate deleted from crates.io | false | crates.io database dump | Yes |
Repository204 stars, 35 forks, 11 contributors, 238 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 204 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 35 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 11 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 238 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | Apache-2.0 | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | CUDA, WebGPU, Metal | crates.io database dump | No | |
| What shows each backend | CUDA: oar-ocr feature cuda, oar-ocr-cli feature cuda, oar-ocr-core feature cuda, oar-ocr-vl feature cuda; WebGPU: oar-ocr feature webgpu, oar-ocr-core feature webgpu; Metal: oar-ocr-cli feature metal, oar-ocr-vl feature metal | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | Binds native code: ort-sys | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | 9 | crates.io database dump | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.