From 04ae6f2a7b27b2b201af73e25064d98724b91edd Mon Sep 17 00:00:00 2001 From: Wang Xin Date: Wed, 15 Jul 2026 16:30:23 +0000 Subject: [PATCH] docs: curate public model references --- README.md | 4 +- docs/FAQ.md | 35 +++--------- docs/environment-variables.md | 2 +- docs/features.md | 2 +- docs/models.md | 57 +++++++------------ docs/usage.md | 13 ++--- examples/auto_download.rs | 2 +- examples/document_orientation.rs | 2 +- examples/document_rectification.rs | 2 +- examples/formula_recognition.rs | 4 +- examples/ocr.rs | 4 +- examples/structure.rs | 46 +++++++-------- examples/table_structure_recognition.rs | 6 +- examples/text_line_orientation.rs | 2 +- examples/text_recognition.rs | 2 +- examples/utils/pdf.rs | 2 +- oar-ocr-core/src/core/download/mod.rs | 10 ++-- oar-ocr-core/src/domain/structure.rs | 2 +- .../src/processors/formula_preprocess.rs | 4 +- oar-ocr-core/src/processors/geometry.rs | 6 +- oar-ocr-core/src/processors/layout_sorting.rs | 6 +- oar-ocr-core/src/processors/simd.rs | 2 +- oar-ocr-vl/README.md | 14 ++--- oar-ocr-vl/examples/paddleocr_vl.rs | 6 +- oar-ocr-vl/examples/utils/mineru_layout.rs | 2 +- oar-ocr-vl/examples/utils/structure_match.rs | 4 +- oar-ocr-vl/src/mineru/model.rs | 4 +- oar-ocr-vl/src/paddleocr_vl/model.rs | 2 +- oar-ocr-vl/src/utils.rs | 10 ++-- oar-ocr-vl/src/utils/table.rs | 6 +- src/oarocr/result.rs | 2 +- src/oarocr/stitching.rs | 12 ++-- 32 files changed, 121 insertions(+), 156 deletions(-) diff --git a/README.md b/README.md index 11a9d10..53a916d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ 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-via-the-auto-download-feature) for model download and cache behavior. +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). @@ -113,7 +113,7 @@ The classic pipeline runs ONNX models through ONNX Runtime and supports the foll 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. -### Vision-Language Models (VLM) +### 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. diff --git a/docs/FAQ.md b/docs/FAQ.md index 291184f..e6eac4e 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -4,29 +4,18 @@ Common build and runtime questions, distilled from GitHub issues. ## Windows: linking fails with `LNK2001: unresolved external symbol __std_find_trivial_8` -Unresolved `__std_*` symbols (`__std_find_trivial_*`, `__std_max_element_*`, -`__std_search_*`, ...) mean the linker's MSVC STL is too old. The prebuilt -ONNX Runtime binaries that `ort-sys` downloads are compiled with Visual -Studio 2022 (MSVC v143) and reference vectorized STL helpers that do not -exist in the VS 2019 (v142) link libraries. +Unresolved `__std_*` symbols (`__std_find_trivial_*`, `__std_max_element_*`, `__std_search_*`, ...) mean the linker's MSVC STL is too old. The prebuilt ONNX Runtime binaries that `ort-sys` downloads are compiled with Visual Studio 2022 (MSVC v143) and reference vectorized STL helpers that do not exist in the VS 2019 (v142) link libraries. Fix: -1. Install **Visual Studio 2022** or **Build Tools for Visual Studio 2022** - with the "Desktop development with C++" workload (MSVC v143 + Windows SDK). -2. Run `cargo clean` and rebuild — rustc picks the newest installed MSVC - toolset automatically. +1. Install **Visual Studio 2022** or **Build Tools for Visual Studio 2022** with the "Desktop development with C++" workload (MSVC v143 + Windows SDK). +2. Run `cargo clean` and rebuild. Rustc picks the newest installed MSVC toolset automatically. -VS 2019 and VS 2022 build tools can coexist; only the newer one needs to be -present for linking. (See issue [#105](https://github.com/GreatV/oar-ocr/issues/105).) +VS 2019 and VS 2022 build tools can coexist. Only the newer one needs to be present for linking. See issue [#105](https://github.com/GreatV/oar-ocr/issues/105). ## GPU inference is slower than CPU for PP-OCRv6 tiny/small -Expected. The tiny/small models are so small that per-call overhead — -host↔device tensor copies, kernel launches, CPU/GPU synchronization, plus -pre/post-processing that always runs on the CPU — outweighs the compute the -GPU saves. Measured on an RTX 4090 + i9-13900KF (single image, warmup -excluded): +Expected. The tiny and small models are so compact that per-call overhead, including host-to-device tensor copies, kernel launches, CPU/GPU synchronization, and CPU pre/post-processing, can outweigh the computation saved by the GPU. The following results were measured on an RTX 4090 with an i9-13900KF using a single image and excluding warmup: | Model | CPU | GPU (CUDA EP) | | ------ | ---------- | ------------------------- | @@ -37,13 +26,7 @@ excluded): Guidelines: - For tiny/small, use the default CPU mode (the `simd` feature is on by default). -- Use the medium model, or batch several images per `predict()` call, when - GPU acceleration matters. -- Exclude the first call when benchmarking: it includes cuDNN initialization - and algorithm selection (~5× slower than steady state). - -Also note that requesting `OrtExecutionProvider::CUDA` without building with -`--features cuda` makes the pipeline builder return an error — check the -`Result` of `.build()`. Without the `cuda` feature, the downloaded ONNX -Runtime is CPU-only and the GPU is never used. -(See issue [#151](https://github.com/GreatV/oar-ocr/issues/151).) +- Use the medium model, or batch several images per `predict()` call, when GPU acceleration matters. +- Exclude the first call when benchmarking because it includes cuDNN initialization and algorithm selection (~5× slower than steady state). + +Also note that requesting `OrtExecutionProvider::CUDA` without building with `--features cuda` makes the pipeline builder return an error. Check the `Result` of `.build()`. Without the `cuda` feature, the downloaded ONNX Runtime is CPU-only and the GPU is never used. See issue [#151](https://github.com/GreatV/oar-ocr/issues/151). diff --git a/docs/environment-variables.md b/docs/environment-variables.md index ed5faf6..af0a3b8 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -28,7 +28,7 @@ Runtime environment variables read by the oar-ocr crates. Project-specific varia ## `OAR_HOME` -Directory where the `auto-download` feature caches model files (default `~/.oar`). Bare model file names passed to the builders are downloaded here and verified against their expected SHA-256. See [models.md](models.md#auto-download-via-the-auto-download-feature) for the exact path resolution rules. +Directory where the `auto-download` feature caches model files (default `~/.oar`). Bare model file names passed to the builders are downloaded here and verified against their expected SHA-256. See [models.md](models.md#auto-download) for the exact path resolution rules. ```bash OAR_HOME=/data/oar-models cargo run --release --example ocr -- doc.jpg diff --git a/docs/features.md b/docs/features.md index b9b4021..33b5107 100644 --- a/docs/features.md +++ b/docs/features.md @@ -159,7 +159,7 @@ If an execution provider feature is enabled, the supplied ONNX Runtime build mus cargo add oar-ocr --features auto-download ``` -Existing files and explicit paths remain under caller control. In-memory ONNX sources also bypass the download resolver. See the [model guide](models.md#auto-download-via-the-auto-download-feature) for the complete path-resolution and cache rules. +Existing files and explicit paths remain under caller control. In-memory ONNX sources also bypass the download resolver. See the [model guide](models.md#auto-download) for the complete path-resolution and cache rules. `auto-download` supplies model files at runtime. It does not install ONNX Runtime or any accelerator dependencies. diff --git a/docs/models.md b/docs/models.md index 495f1a4..b102fbd 100644 --- a/docs/models.md +++ b/docs/models.md @@ -1,6 +1,6 @@ # Pre-trained Models -OAROCR provides pre-trained models for OCR and document understanding tasks. Download them manually from the [GitHub Releases](https://github.com/GreatV/oar-ocr/releases) page (linked in the tables below), or have the library fetch them on demand from ModelScope — see [Auto-download](#auto-download-via-the-auto-download-feature) at the bottom. +OAROCR provides pre-trained models for OCR and document understanding tasks. Download them manually from the [GitHub Releases](https://github.com/GreatV/oar-ocr/releases) page (linked in the tables below), or have the library fetch them on demand from ModelScope. See [Auto-download](#auto-download) at the bottom. ## Text Detection Models @@ -61,7 +61,7 @@ Choose between mobile and server variants based on your needs: ## PP-OCRv6 -PP-OCRv6 is the newest PP-OCR generation. Unlike the older models mirrored on this project's GitHub Releases, the v6 ONNX models are referenced **directly from PaddlePaddle's official channels**. +PP-OCRv6 is the newest PP-OCR generation. The flat ONNX files and dictionaries are published in this project's [`v0.7.0` release](https://github.com/GreatV/oar-ocr/releases/tag/v0.7.0) and on ModelScope. The tables also link the original PaddlePaddle inference bundles. > **Source / attribution.** Published by PaddlePaddle under the [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) project (Apache-2.0). @@ -69,17 +69,17 @@ PP-OCRv6 is the newest PP-OCR generation. Unlike the older models mirrored on th | Size | Auto-download ONNX | File size | Official bundle | |------|--------------------|-----------|-----------------| -| tiny | `pp-ocrv6_tiny_det.onnx` | 1.7 MiB | [`PP-OCRv6_tiny_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_tiny_det_onnx_infer.tar) | -| small | `pp-ocrv6_small_det.onnx` | 9.4 MiB | [`PP-OCRv6_small_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_small_det_onnx_infer.tar) | -| medium | `pp-ocrv6_medium_det.onnx` | 59.2 MiB | [`PP-OCRv6_medium_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_medium_det_onnx_infer.tar) | +| tiny | [`pp-ocrv6_tiny_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_tiny_det.onnx) | 1.7 MiB | [`PP-OCRv6_tiny_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_tiny_det_onnx_infer.tar) | +| small | [`pp-ocrv6_small_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_small_det.onnx) | 9.4 MiB | [`PP-OCRv6_small_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_small_det_onnx_infer.tar) | +| medium | [`pp-ocrv6_medium_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_medium_det.onnx) | 59.2 MiB | [`PP-OCRv6_medium_det_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_medium_det_onnx_infer.tar) | ### Recognition | Size | Auto-download ONNX | Dictionary | File size | Official bundle | |------|--------------------|------------|-----------|-----------------| -| tiny | `pp-ocrv6_tiny_rec.onnx` | `ppocrv6_tiny_dict.txt` (6904 characters) | 4.3 MiB | [`PP-OCRv6_tiny_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_tiny_rec_onnx_infer.tar) | -| small | `pp-ocrv6_small_rec.onnx` | `ppocrv6_dict.txt` (18708 characters) | 20.2 MiB | [`PP-OCRv6_small_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_small_rec_onnx_infer.tar) | -| medium | `pp-ocrv6_medium_rec.onnx` | `ppocrv6_dict.txt` (18708 characters) | 73.0 MiB | [`PP-OCRv6_medium_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_medium_rec_onnx_infer.tar) | +| tiny | [`pp-ocrv6_tiny_rec.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_tiny_rec.onnx) | [`ppocrv6_tiny_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/ppocrv6_tiny_dict.txt) (6904 characters) | 4.3 MiB | [`PP-OCRv6_tiny_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_tiny_rec_onnx_infer.tar) | +| small | [`pp-ocrv6_small_rec.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_small_rec.onnx) | [`ppocrv6_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/ppocrv6_dict.txt) (18708 characters) | 20.2 MiB | [`PP-OCRv6_small_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_small_rec_onnx_infer.tar) | +| medium | [`pp-ocrv6_medium_rec.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/pp-ocrv6_medium_rec.onnx) | [`ppocrv6_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/ppocrv6_dict.txt) (18708 characters) | 73.0 MiB | [`PP-OCRv6_medium_rec_onnx_infer.tar`](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/PP-OCRv6_medium_rec_onnx_infer.tar) | ## Character Dictionaries @@ -91,8 +91,8 @@ Character dictionaries are required for text recognition. Choose the appropriate |---------|------|-------------| | PP-OCRv4 Document | [`ppocrv4_doc_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/ppocrv4_doc_dict.txt) | For PP-OCRv4 document models | | PP-OCRv5 | [`ppocrv5_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/ppocrv5_dict.txt) | For PP-OCRv5 models | -| PP-OCRv6 Tiny | `ppocrv6_tiny_dict.txt` | For PP-OCRv6 tiny recognition | -| PP-OCRv6 Small/Medium | `ppocrv6_dict.txt` | For PP-OCRv6 small and medium recognition | +| PP-OCRv6 Tiny | [`ppocrv6_tiny_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/ppocrv6_tiny_dict.txt) | For PP-OCRv6 tiny recognition | +| PP-OCRv6 Small/Medium | [`ppocrv6_dict.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.7.0/ppocrv6_dict.txt) | For PP-OCRv6 small and medium recognition | | PP-OCR Keys v1 | [`ppocr_keys_v1.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/ppocr_keys_v1.txt) | For PP-OCRv3 general and PP-OCRv4 general models | ### PP-OCRv5 Language-Specific Dictionaries @@ -137,7 +137,6 @@ Models for document preprocessing and orientation detection: |------|------------|------|-------------| | Document Orientation | [`pp-lcnet_x1_0_doc_ori.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-lcnet_x1_0_doc_ori.onnx) | 6.5 MiB | Detect document rotation | | Text Line Orientation (Light) | [`pp-lcnet_x0_25_textline_ori.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-lcnet_x0_25_textline_ori.onnx) | 995 KiB | Fast text line orientation | -| Text Line Orientation (Paddle2ONNX) | `p2o_pp-lcnet_x0_25_textline_ori.onnx` | 977 KiB | Compatibility export available through auto-download | | Text Line Orientation | [`pp-lcnet_x1_0_textline_ori.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-lcnet_x1_0_textline_ori.onnx) | 6.5 MiB | Accurate text line orientation | | Document Rectification | [`uvdoc.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/uvdoc.onnx) | 30.2 MiB | Fix perspective distortion | @@ -174,7 +173,6 @@ Models for document structure analysis with `OARStructureBuilder`: | Cell Detection (Wireless) | [`rt-detr-l_wireless_table_cell_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/rt-detr-l_wireless_table_cell_det.onnx) | 123.3 MiB | RT-DETR for wireless tables | | Structure (SLANet) | [`slanet.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/slanet.onnx) | 7.4 MiB | Basic structure recognition | | Structure (SLANet+) | [`slanet_plus.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/slanet_plus.onnx) | 7.4 MiB | Wireless table structure | -| Structure (SLANet+ V2) | `slanet_plus_v2.onnx` | 7.4 MiB | Newer compatibility export available through auto-download | | Structure (SLANeXt Wired) | [`slanext_wired.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/slanext_wired.onnx) | 350.7 MiB | High accuracy wired structure | | Structure (SLANeXt Wireless) | [`slanext_wireless.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/slanext_wireless.onnx) | 350.7 MiB | High accuracy wireless structure | | Structure Dictionary | [`table_structure_dict_ch.txt`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/table_structure_dict_ch.txt) | - | Required for structure recognition | @@ -188,19 +186,10 @@ Models for document structure analysis with `OARStructureBuilder`: | PP-FormulaNet_plus-S | [`pp-formulanet_plus-s.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-formulanet_plus-s.onnx) | 221.1 MiB | Enhanced small variant | | PP-FormulaNet_plus-M | [`pp-formulanet_plus-m.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-formulanet_plus-m.onnx) | 564.9 MiB | Enhanced medium variant | | PP-FormulaNet_plus-L | [`pp-formulanet_plus-l.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-formulanet_plus-l.onnx) | 699.5 MiB | Enhanced large variant | -| PP-FormulaNet Tokenizer | `pp-formulanet-tokenizer.json` | 2.0 MiB | Required for PP-FormulaNet variants | +| PP-FormulaNet Tokenizer | [`pp-formulanet-tokenizer.json`](https://www.modelscope.cn/models/greatv/oar-ocr/file/view/master/pp-formulanet-tokenizer.json) | 2.0 MiB | Required for PP-FormulaNet variants | | UniMERNet | [`unimernet.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/unimernet.onnx) | 1.7 GiB | Unified Math Expression Recognition | | UniMERNet Tokenizer | [`unimernet_tokenizer.json`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/unimernet_tokenizer.json) | 2.0 MiB | Required for UniMERNet | -The current formula predictor supports PP-FormulaNet and UniMERNet. `latex_ocr_rec.onnx` remains registered as a legacy download artifact, but it is not wired into `FormulaRecognitionPredictor` and its tokenizer is not mirrored by this project. - -### Auxiliary and Legacy Registered Assets - -| Asset | Size | Status | -|-------|------|--------| -| [`latex_ocr_rec.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/latex_ocr_rec.onnx) | 97.8 MiB | Legacy checkpoint, not supported by the current formula predictor | -| `unimernet_tokenizer_config.json` | 4.4 KiB | Optional tokenizer metadata retained for compatibility | - ### Seal Text Detection | Model | Model File | Size | Description | @@ -208,7 +197,7 @@ The current formula predictor supports PP-FormulaNet and UniMERNet. `latex_ocr_r | Seal Detection (Mobile) | [`pp-ocrv4_mobile_seal_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-ocrv4_mobile_seal_det.onnx) | 4.6 MiB | Fast seal detection | | Seal Detection (Server) | [`pp-ocrv4_server_seal_det.onnx`](https://github.com/GreatV/oar-ocr/releases/download/v0.3.0/pp-ocrv4_server_seal_det.onnx) | 108.2 MiB | Accurate seal detection | -## Auto-download (via the `auto-download` feature) +## Auto-download ```bash cargo add oar-ocr --features auto-download @@ -217,7 +206,7 @@ cargo add oar-ocr --features auto-download ```rust,no_run use oar_ocr::prelude::*; let ocr = OAROCRBuilder::new( - "pp-ocrv5_mobile_det.onnx", // bare name → resolved via registry + "pp-ocrv5_mobile_det.onnx", // bare name resolved through the registry "pp-ocrv5_mobile_rec.onnx", "ppocrv5_dict.txt", ).build()?; @@ -228,32 +217,30 @@ When the feature is enabled, registered file names are fetched from [`greatv/oar ### Path resolution rules -These rules apply to *path* sources only; models passed as in-memory bytes -(see [Loading Models from Memory](usage.md#loading-models-from-memory)) bypass -path resolution entirely. +These rules apply only to *path* sources. Models passed as in-memory bytes (see [Loading Models from Memory](usage.md#loading-models-from-memory)) bypass path resolution entirely. For each model path argument the builder applies these checks in order: 1. **Existing file wins.** If the path refers to a real file on disk it is used as-is — no registry lookup, no hash check, no network. A `./pp-ocrv5_mobile_det.onnx` next to the binary always shadows the registry. 2. **Only bare names or `$OAR_HOME`-rooted paths are eligible for auto-download.** A path is considered for registry resolution only when it has no parent component (e.g. `"pp-ocrv5_mobile_det.onnx"`) or when its parent equals the cache directory. Explicit paths like `./models/foo.onnx` or `/data/foo.onnx` are returned verbatim even if their file name is registered — the library never silently overrides an explicit path. -3. **Registry hit → cache or download.** If the file name appears in `REGISTRY`: - - `$OAR_HOME/` exists with matching size + SHA-256 → cached copy is used (no network). - - Cached copy is missing or its hash mismatches → download from ModelScope, verify SHA-256, atomically replace. -4. **Unregistered + missing → returned verbatim** so the builder produces its normal "model not found" error. +3. **Registry hit: cache or download.** If the file name appears in `REGISTRY`: + - The cached copy is used without network access when `$OAR_HOME/` exists with the expected size and SHA-256. + - Otherwise, the file is downloaded from ModelScope, verified with SHA-256, and atomically replaced. +4. **Unregistered and missing.** The path is returned verbatim so the builder produces its normal "model not found" error. | Input | On disk | Behaviour | |---|---|---| | `"pp-ocrv5_mobile_det.onnx"` | `./pp-ocrv5_mobile_det.onnx` exists | Use the local CWD file | | `"pp-ocrv5_mobile_det.onnx"` | `$OAR_HOME/...` exists, hash OK | Use cached copy, no network | | `"pp-ocrv5_mobile_det.onnx"` | absent or hash mismatch | Download to `$OAR_HOME`, verify, use | -| `"./models/det.onnx"` | absent | Returned as-is → "model not found" | -| `"$OAR_HOME/pp-ocrv5_mobile_det.onnx"` (absolute) | (any) | Parent equals the cache dir → same as bare name | +| `"./models/det.onnx"` | absent | Returned as-is, resulting in "model not found" | +| `"$OAR_HOME/pp-ocrv5_mobile_det.onnx"` (absolute) | (any) | Handled like a bare name because its parent is the cache directory | Note: the resolver compares paths verbatim — `~` is not expanded. Pass a bare filename, an absolute path under `$OAR_HOME`, or let your shell expand `~` for you. ### Cache layout -- Override the cache root with the `OAR_HOME` environment variable. Defaults to `~/.oar` (resolved via the platform home directory; the literal `~` is not expanded by the library). +- Override the cache root with the `OAR_HOME` environment variable. Defaults to `~/.oar` (resolved via the platform home directory, while the literal `~` is not expanded by the library). - Files land at `$OAR_HOME/`, flat (no per-revision subdirectories). - Downloads stream into a unique `$OAR_HOME/....part` and are renamed atomically once the SHA-256 matches, so a crash mid-download won't poison the cache and concurrent processes don't clobber each other. -- After verification a `$OAR_HOME/..sha256` sidecar records the verified hash. Future loads with a matching cache file + sidecar skip the multi-second rehash; deleting the sidecar forces a fresh hash check. +- After verification a `$OAR_HOME/..sha256` sidecar records the verified hash. Future loads with a matching cache file + sidecar skip the multi-second rehash. Deleting the sidecar forces a fresh hash check. diff --git a/docs/usage.md b/docs/usage.md index cfce743..2f5bd62 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -105,9 +105,7 @@ let ocr = OAROCRBuilder::new( #### Loading Models from Memory -Everywhere a builder accepts a model path it also accepts raw ONNX bytes -(`Vec`, `&'static [u8]`, or `Arc<[u8]>`), so models can be embedded into -the binary or decrypted at runtime without touching the filesystem: +Everywhere a builder accepts a model path it also accepts raw ONNX bytes (`Vec`, `&'static [u8]`, or `Arc<[u8]>`), so models can be embedded into the binary or decrypted at runtime without touching the filesystem: ```rust use oar_ocr::oarocr::OAROCRBuilder; @@ -121,10 +119,7 @@ let ocr = OAROCRBuilder::new(DET_MODEL, REC_MODEL, "") .build()?; ``` -In-memory sources skip auto-download resolution, and models that reference -external-data sidecar files cannot be loaded this way. The same applies to -the per-task predictors (`TextDetectionPredictorBuilder::build(...)` etc.), -`OARStructureBuilder` model setters, and `AdapterBuilder::build(...)`. +In-memory sources skip auto-download resolution, and models that reference external-data sidecar files cannot be loaded this way. The same applies to the per-task predictors (`TextDetectionPredictorBuilder::build(...)` etc.), `OARStructureBuilder` model setters, and `AdapterBuilder::build(...)`. ### OARStructureBuilder - Document Structure Analysis @@ -262,7 +257,7 @@ let ort_config = OrtSessionConfig::new() ]); ``` -## PaddleOCR-VL (Vision-Language) +## PaddleOCR-VL [PaddleOCR-VL](https://huggingface.co/PaddlePaddle/PaddleOCR-VL) is a 0.9B document Vision-Language Model from the PaddlePaddle team. It supports 109 languages and task-specific recognition for text, tables, formulas, and charts. @@ -295,7 +290,7 @@ On macOS, use the `metal` feature instead. Download the PaddleOCR-VL model from Hugging Face: ```bash -# Using git (recommended) +# Recommended git download git lfs install git clone https://huggingface.co/PaddlePaddle/PaddleOCR-VL diff --git a/examples/auto_download.rs b/examples/auto_download.rs index 57113b7..ed863e4 100644 --- a/examples/auto_download.rs +++ b/examples/auto_download.rs @@ -43,7 +43,7 @@ fn main() -> Result<(), Box> { println!("OAR cache: {}", oar_ocr::download::cache_dir().display()); - // Bare file names → resolved through the registry on `build()`. + // Bare file names are resolved through the registry on `build()`. // The first run downloads to ~/.oar (or $OAR_HOME); subsequent runs reuse // the cached copies after verifying their SHA-256. let ocr = OAROCRBuilder::new( diff --git a/examples/document_orientation.rs b/examples/document_orientation.rs index a45787e..224a339 100644 --- a/examples/document_orientation.rs +++ b/examples/document_orientation.rs @@ -22,7 +22,7 @@ //! //! ```bash //! cargo run --example document_orientation -- \ -//! -m models/pplcnet_x1_0_doc_ori.onnx \ +//! -m models/pp-lcnet_x1_0_doc_ori.onnx \ //! -o output/ --vis \ //! document1.jpg document2.jpg //! ``` diff --git a/examples/document_rectification.rs b/examples/document_rectification.rs index 3f77f00..6bcf404 100644 --- a/examples/document_rectification.rs +++ b/examples/document_rectification.rs @@ -22,7 +22,7 @@ //! //! ```bash //! cargo run --example document_rectification -- \ -//! -m models/uvdoc_rectifier.onnx \ +//! -m models/uvdoc.onnx \ //! -o output/ --vis \ //! distorted_doc1.jpg distorted_doc2.jpg //! ``` diff --git a/examples/formula_recognition.rs b/examples/formula_recognition.rs index dd0acbb..7917684 100644 --- a/examples/formula_recognition.rs +++ b/examples/formula_recognition.rs @@ -37,8 +37,8 @@ //! Basic usage: //! ```bash //! cargo run --example formula_recognition -- \ -//! -m models/PP-FormulaNet_plus-M/inference.onnx \ -//! -t models/PP-FormulaNet_plus-M/tokenizer.json \ +//! -m models/pp-formulanet_plus-m.onnx \ +//! -t models/pp-formulanet-tokenizer.json \ //! --model-name "PP-FormulaNet_plus-M" \ //! formula1.jpg formula2.jpg //! ``` diff --git a/examples/ocr.rs b/examples/ocr.rs index 0639f53..2a91d68 100644 --- a/examples/ocr.rs +++ b/examples/ocr.rs @@ -34,8 +34,8 @@ //! //! ```bash //! cargo run --example ocr -- \ -//! --det-model models/ppocrv4_mobile_det.onnx \ -//! --rec-model models/ppocrv4_mobile_rec.onnx \ +//! --det-model models/pp-ocrv4_mobile_det.onnx \ +//! --rec-model models/pp-ocrv4_mobile_rec.onnx \ //! --dict-path models/ppocr_keys_v1.txt \ //! document1.jpg document2.jpg //! ``` diff --git a/examples/structure.rs b/examples/structure.rs index b8e1a71..538d520 100644 --- a/examples/structure.rs +++ b/examples/structure.rs @@ -64,12 +64,12 @@ //! //! # Examples //! -//! ## Minimal (Layout Detection Only) +//! ## Minimal Layout Detection //! //! ```bash //! cargo run --release --features cuda --example structure -- \ -//! --layout-model models/PP-DocLayout_plus-L.onnx \ -//! --region-model models/PP-DocBlockLayout.onnx \ +//! --layout-model models/pp-doclayout_plus-l.onnx \ +//! --region-model models/pp-docblocklayout.onnx \ //! document.jpg //! ``` //! @@ -77,10 +77,10 @@ //! //! ```bash //! cargo run --release --features cuda --example structure -- \ -//! --layout-model models/PP-DocLayout_plus-L.onnx \ -//! --region-model models/PP-DocBlockLayout.onnx \ -//! --text-det-model models/PP-OCRv5_server_det.onnx \ -//! --text-rec-model models/PP-OCRv5_server_rec.onnx \ +//! --layout-model models/pp-doclayout_plus-l.onnx \ +//! --region-model models/pp-docblocklayout.onnx \ +//! --text-det-model models/pp-ocrv5_server_det.onnx \ +//! --text-rec-model models/pp-ocrv5_server_rec.onnx \ //! --text-dict-path models/ppocrv5_dict.txt \ //! document.jpg //! ``` @@ -89,7 +89,7 @@ //! //! ```bash //! cargo run --release --features cuda --example structure -- \ -//! --layout-model models/PicoDet-L_layout_17cls.onnx \ +//! --layout-model models/picodet-l_layout_17cls.onnx \ //! --layout-model-name PicoDet-L_layout_17cls \ //! document.jpg //! ``` @@ -98,29 +98,29 @@ //! //! ```bash //! cargo run --release --features cuda --example structure -- \ -//! --layout-model models/PP-DocLayout_plus-L.onnx \ -//! --region-model models/PP-DocBlockLayout.onnx \ -//! --orientation-model models/PP-LCNet_x1_0_doc_ori.onnx \ -//! --rectification-model models/UVDoc.onnx \ -//! --table-cls-model models/PP-LCNet_x1_0_table_cls.onnx \ -//! --wired-structure-model models/SLANeXt_wired.onnx \ -//! --wireless-structure-model models/SLANet_plus.onnx \ -//! --wired-cell-model models/RT-DETR-L_wired_table_cell_det.onnx \ -//! --wireless-cell-model models/RT-DETR-L_wireless_table_cell_det.onnx \ +//! --layout-model models/pp-doclayout_plus-l.onnx \ +//! --region-model models/pp-docblocklayout.onnx \ +//! --orientation-model models/pp-lcnet_x1_0_doc_ori.onnx \ +//! --rectification-model models/uvdoc.onnx \ +//! --table-cls-model models/pp-lcnet_x1_0_table_cls.onnx \ +//! --wired-structure-model models/slanext_wired.onnx \ +//! --wireless-structure-model models/slanet_plus.onnx \ +//! --wired-cell-model models/rt-detr-l_wired_table_cell_det.onnx \ +//! --wireless-cell-model models/rt-detr-l_wireless_table_cell_det.onnx \ //! --table-structure-dict models/table_structure_dict_ch.txt \ -//! --formula-model models/PP-FormulaNet_plus-L.onnx \ -//! --formula-tokenizer models/pp_formulanet_tokenizer.json \ +//! --formula-model models/pp-formulanet_plus-l.onnx \ +//! --formula-tokenizer models/pp-formulanet-tokenizer.json \ //! --formula-type pp_formulanet \ -//! --seal-model models/PP-OCRv4_server_seal_det.onnx \ -//! --text-det-model models/PP-OCRv5_server_det.onnx \ -//! --text-rec-model models/PP-OCRv5_server_rec.onnx \ +//! --seal-model models/pp-ocrv4_server_seal_det.onnx \ +//! --text-det-model models/pp-ocrv5_server_det.onnx \ +//! --text-rec-model models/pp-ocrv5_server_rec.onnx \ //! --text-dict-path models/ppocrv5_dict.txt \ //! --to-json --to-markdown \ //! -o output/structure \ //! document.jpg //! ``` //! -//! # Model Reference (PP-StructureV3 Defaults) +//! # PP-StructureV3 Default Model Reference //! //! | Component | Model Name | Model Path Arg | Model Name Arg | //! |-----------|------------|----------------|----------------| diff --git a/examples/table_structure_recognition.rs b/examples/table_structure_recognition.rs index ea7bf49..f02e4c0 100644 --- a/examples/table_structure_recognition.rs +++ b/examples/table_structure_recognition.rs @@ -28,7 +28,7 @@ //! cargo run --example table_structure_recognition -- \ //! --model-path path/to/model.onnx \ //! --dict-path path/to/dict.txt \ -//! --image-path path/to/image.jpg +//! path/to/image.jpg //! ``` //! //! With custom dictionary: @@ -37,7 +37,7 @@ //! cargo run --example table_structure_recognition -- \ //! --model-path path/to/model.onnx \ //! --dict-path path/to/table_structure_dict_ch.txt \ -//! --image-path path/to/image.jpg +//! path/to/image.jpg //! ``` //! //! With wireless table model (requires different dictionary): @@ -47,7 +47,7 @@ //! --model-path path/to/model.onnx \ //! --dict-path path/to/table_structure_dict.txt \ //! --model-name SLANet_plus \ -//! --image-path path/to/image.jpg +//! path/to/image.jpg //! ``` mod utils; diff --git a/examples/text_line_orientation.rs b/examples/text_line_orientation.rs index 11d7147..5736b9d 100644 --- a/examples/text_line_orientation.rs +++ b/examples/text_line_orientation.rs @@ -22,7 +22,7 @@ //! //! ```bash //! cargo run --example text_line_orientation -- \ -//! -m models/pplcnet_x1_0_textline_ori.onnx \ +//! -m models/pp-lcnet_x1_0_textline_ori.onnx \ //! -o output/ --vis \ //! text_line1.jpg text_line2.jpg //! ``` diff --git a/examples/text_recognition.rs b/examples/text_recognition.rs index a379289..79af806 100644 --- a/examples/text_recognition.rs +++ b/examples/text_recognition.rs @@ -23,7 +23,7 @@ //! //! ```bash //! cargo run --example text_recognition -- \ -//! -m models/ppocrv4_mobile_rec.onnx \ +//! -m models/pp-ocrv4_mobile_rec.onnx \ //! -d models/ppocr_keys_v1.txt \ //! -o output/ --vis \ //! text1.jpg text2.jpg diff --git a/examples/utils/pdf.rs b/examples/utils/pdf.rs index 5b79e8e..50c1161 100644 --- a/examples/utils/pdf.rs +++ b/examples/utils/pdf.rs @@ -129,7 +129,7 @@ impl PdfDocument { }; // Create render settings (hayro defaults bg_color to TRANSPARENT; - // we need WHITE so the RGBA→RGB conversion produces a white background) + // we need WHITE so the RGBA-to-RGB conversion produces a white background) let settings = RenderSettings { x_scale: scale, y_scale: scale, diff --git a/oar-ocr-core/src/core/download/mod.rs b/oar-ocr-core/src/core/download/mod.rs index 1b8b15e..f996210 100644 --- a/oar-ocr-core/src/core/download/mod.rs +++ b/oar-ocr-core/src/core/download/mod.rs @@ -508,7 +508,7 @@ mod tests { #[test] fn resolve_bare_name_unknown_does_not_consult_network() { let _guard = lock_env(); - // No registry hit, no existing file → returned as-is. + // A path with no registry hit and no existing file is returned as-is. let p = PathBuf::from("not-in-registry.onnx"); let resolved = resolve_path(&p).unwrap(); assert_eq!(resolved, p); @@ -540,18 +540,18 @@ mod tests { size: 6, }; - // Missing file → no match (no network needed). + // A missing file does not match, and no network access is needed. assert!(!cached_file_matches(&path, &entry).unwrap()); - // Correct contents → match. + // Correct contents produce a match. std::fs::write(&path, b"hello\n").unwrap(); assert!(cached_file_matches(&path, &entry).unwrap()); - // Same hash but wrong size when we lie about expected size → no match. + // The same hash with a deliberately incorrect expected size does not match. let mismatched_size = Entry { size: 99, ..entry }; assert!(!cached_file_matches(&path, &mismatched_size).unwrap()); - // Wrong contents → no match (hash differs). Clear any sidecar left + // Wrong contents do not match because the hash differs. Clear any sidecar left // behind by the earlier matches so the rehash actually runs. let sidecar = sidecar_path(&path).unwrap(); let _ = std::fs::remove_file(&sidecar); diff --git a/oar-ocr-core/src/domain/structure.rs b/oar-ocr-core/src/domain/structure.rs index 0c1b394..f81919e 100644 --- a/oar-ocr-core/src/domain/structure.rs +++ b/oar-ocr-core/src/domain/structure.rs @@ -1458,7 +1458,7 @@ fn dehyphenate(text: &str) -> String { } // Only dehyphenate when hyphen is followed by newline (line-break hyphenation). - // Pattern: "word-\nletter" → "wordletter" + // Pattern: "word-\nletter" becomes "wordletter". let is_artifact = if i + 1 < len && chars[i + 1] == '\n' { // Hyphen followed by newline — check if next line starts with lowercase if i + 2 < len { diff --git a/oar-ocr-core/src/processors/formula_preprocess.rs b/oar-ocr-core/src/processors/formula_preprocess.rs index 47f1a60..e678ea9 100644 --- a/oar-ocr-core/src/processors/formula_preprocess.rs +++ b/oar-ocr-core/src/processors/formula_preprocess.rs @@ -40,8 +40,8 @@ pub struct FormulaPreprocessParams { pub normalize_std: [f32; 3], } -/// Formula recognition preprocessor: margin crop → resize-and-pad → -/// normalize-and-grayscale → 4D tensor formatting. +/// Formula recognition preprocessor with margin cropping, resize-and-pad, +/// normalization and grayscale conversion, followed by 4D tensor formatting. #[derive(Debug, Clone)] pub struct FormulaPreprocessor { params: FormulaPreprocessParams, diff --git a/oar-ocr-core/src/processors/geometry.rs b/oar-ocr-core/src/processors/geometry.rs index bc60732..62d6aff 100644 --- a/oar-ocr-core/src/processors/geometry.rs +++ b/oar-ocr-core/src/processors/geometry.rs @@ -860,19 +860,19 @@ impl BoundingBox { 90 => { // Image was rotated 270° counter-clockwise (or 90° clockwise) to correct // Inverse: rotate box 90° clockwise - // (x, y) in rotated → (rotated_height - y, x) in original + // Map (x, y) in the rotated image to (rotated_height - y, x) in the original. Point::new(rotated_height as f32 - p.y, p.x) } 180 => { // Image was rotated 180° to correct // Inverse: rotate box 180° - // (x, y) in rotated → (rotated_width - x, rotated_height - y) in original + // Map (x, y) in the rotated image to (rotated_width - x, rotated_height - y) in the original. Point::new(rotated_width as f32 - p.x, rotated_height as f32 - p.y) } 270 => { // Image was rotated 90° counter-clockwise (or 270° clockwise) to correct // Inverse: rotate box 270° clockwise (or 90° counter-clockwise) - // (x, y) in rotated → (y, rotated_width - x) in original + // Map (x, y) in the rotated image to (y, rotated_width - x) in the original. Point::new(p.y, rotated_width as f32 - p.x) } _ => { diff --git a/oar-ocr-core/src/processors/layout_sorting.rs b/oar-ocr-core/src/processors/layout_sorting.rs index 81a9eda..f99b3bd 100644 --- a/oar-ocr-core/src/processors/layout_sorting.rs +++ b/oar-ocr-core/src/processors/layout_sorting.rs @@ -6,7 +6,7 @@ //! 3. Direction-aware XY-cut sorting //! 4. Overlapping box shrinking before projection //! 5. Weighted distance insertion for special blocks -//! 6. Child block association (vision titles → vision parents) +//! 6. Child block association between vision titles and vision parents use crate::domain::structure::LayoutElementType; use crate::processors::sorting::calculate_overlap_ratio; @@ -274,8 +274,8 @@ fn sort_main_blocks(mut blocks: Vec, page_width: f32) -> Vec Vec { let bboxes: Vec = blocks.iter().map(|b| b.bbox.clone()).collect(); let max_text_lines = blocks.iter().map(|b| b.num_lines).max().unwrap_or(1); diff --git a/oar-ocr-core/src/processors/simd.rs b/oar-ocr-core/src/processors/simd.rs index ae28fd5..72e2c9d 100644 --- a/oar-ocr-core/src/processors/simd.rs +++ b/oar-ocr-core/src/processors/simd.rs @@ -230,7 +230,7 @@ fn reduce_max_simd(row: &[f32]) -> f32 { // CRNN recognition normalize: `(v / 255.0 - 0.5) / 0.5` in BGR order. -/// BGR source-channel order for the CRNN tensor (dst channel 0 ← src B, etc.). +/// BGR source-channel order for the CRNN tensor (destination channel 0 uses source B, etc.). const CRNN_SRC: [usize; 3] = [2, 1, 0]; /// Fills a CRNN CHW input tensor from a resized RGB crop. diff --git a/oar-ocr-vl/README.md b/oar-ocr-vl/README.md index ffae515..e19a632 100644 --- a/oar-ocr-vl/README.md +++ b/oar-ocr-vl/README.md @@ -170,7 +170,7 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example do HunyuanOCR and the MinerU models are intentionally not exposed by this example because their reference-quality paths are prompt-driven full-page parsing and model-native two-step extraction, respectively. -### PaddleOCR-VL (Direct Inference) +### PaddleOCR-VL Direct Inference Run the PaddleOCR-VL model directly on an image with a specific task prompt. @@ -189,14 +189,14 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example pa --task table \ table.jpg -# Text spotting (PaddleOCR-VL-1.5 or 1.6) +# Text spotting with PaddleOCR-VL-1.5 or 1.6 cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example paddleocr_vl -- \ --model-dir models/PaddleOCR-VL-1.5 \ --device cuda \ --task spotting \ spotting.jpg -# Seal recognition (PaddleOCR-VL-1.5 or 1.6) +# Seal recognition with PaddleOCR-VL-1.5 or 1.6 cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example paddleocr_vl -- \ --model-dir models/PaddleOCR-VL-1.6 \ --device cuda \ @@ -204,7 +204,7 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example pa seal.jpg ``` -### HunyuanOCR 1.5 (Direct Inference) +### HunyuanOCR 1.5 Direct Inference ```bash cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example hunyuanocr -- \ @@ -217,7 +217,7 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example hu The model repository root contains HunyuanOCR 1.5. The loader detects it automatically. Use `--model-dir models/HunyuanOCR/v1.0` for the archived 1.0 checkpoint. `--dflash-dir` enables the official 15-token parallel draft path for 1.5. Omit it for ordinary autoregressive decoding. Library callers can use `HunyuanOcr::from_dirs(target_dir, dflash_dir, device)` or `HunyuanOcr::from_dir_with_dflash(model_dir, device)` when the draft is stored in the official `dflash/` subdirectory. -### GLM-OCR (Direct Inference) +### GLM-OCR Direct Inference ```bash cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example glmocr -- \ @@ -227,7 +227,7 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example gl document.jpg ``` -### MinerU2.5 / MinerU2.5-Pro (Direct Inference) +### MinerU2.5 and MinerU2.5-Pro Direct Inference Model-native two-step document extraction (layout prompt + content extraction): @@ -247,7 +247,7 @@ cargo run --release -p oar-ocr-vl --features cuda,download-binaries --example mi document.jpg ``` -### MinerU-Diffusion-V1 (Direct Inference) +### MinerU-Diffusion-V1 Direct Inference The default mode performs two-step structured extraction with block-diffusion decoding. Add `--single-pass` for flat full-page text recognition. diff --git a/oar-ocr-vl/examples/paddleocr_vl.rs b/oar-ocr-vl/examples/paddleocr_vl.rs index 60b7e61..2c02851 100644 --- a/oar-ocr-vl/examples/paddleocr_vl.rs +++ b/oar-ocr-vl/examples/paddleocr_vl.rs @@ -22,7 +22,7 @@ //! # Examples //! //! ```bash -//! # OCR (text recognition) +//! # OCR text recognition //! cargo run -p oar-ocr-vl --features download-binaries --example paddleocr_vl -- \ //! -m PaddleOCR-VL --task ocr document.jpg //! @@ -38,11 +38,11 @@ //! cargo run -p oar-ocr-vl --features download-binaries --example paddleocr_vl -- \ //! -m PaddleOCR-VL --task chart chart.jpg //! -//! # Text spotting (PaddleOCR-VL-1.5 or 1.6) +//! # Text spotting with PaddleOCR-VL-1.5 or 1.6 //! cargo run -p oar-ocr-vl --features download-binaries --example paddleocr_vl -- \ //! -m PaddleOCR-VL-1.5 --task spotting spotting.jpg //! -//! # Seal recognition (PaddleOCR-VL-1.5 or 1.6) +//! # Seal recognition with PaddleOCR-VL-1.5 or 1.6 //! cargo run -p oar-ocr-vl --features download-binaries --example paddleocr_vl -- \ //! -m PaddleOCR-VL-1.6 --task seal seal.jpg //! diff --git a/oar-ocr-vl/examples/utils/mineru_layout.rs b/oar-ocr-vl/examples/utils/mineru_layout.rs index 85223d1..90e008f 100644 --- a/oar-ocr-vl/examples/utils/mineru_layout.rs +++ b/oar-ocr-vl/examples/utils/mineru_layout.rs @@ -1,5 +1,5 @@ //! Shared MinerU two-step layout parsing helpers for the `mineru` and -//! `mineru_diffusion` examples. Both run the same `Layout Detection` → +//! `mineru_diffusion` examples. Both run the same `Layout Detection`, followed by //! per-region recognition flow and only differ in the model's generate API, //! so the layout-output parsing and crop preparation live here. diff --git a/oar-ocr-vl/examples/utils/structure_match.rs b/oar-ocr-vl/examples/utils/structure_match.rs index 2386dcb..9e8037f 100644 --- a/oar-ocr-vl/examples/utils/structure_match.rs +++ b/oar-ocr-vl/examples/utils/structure_match.rs @@ -290,7 +290,7 @@ mod tests { assert!(!m.same_category); } - /// Table → table candidate at relaxed threshold (the candidate set + /// A table target matches a table candidate at a relaxed threshold (the candidate set /// is already type-restricted, so a low IoU floor is safe). #[test] fn table_target_uses_relaxed_threshold() { @@ -305,7 +305,7 @@ mod tests { assert!(m.same_category); } - /// Formula → formula candidate at relaxed threshold. + /// A formula target matches a formula candidate at a relaxed threshold. #[test] fn formula_target_uses_relaxed_threshold() { let mut r = empty_result(); diff --git a/oar-ocr-vl/src/mineru/model.rs b/oar-ocr-vl/src/mineru/model.rs index 27ab66c..4b5cfdb 100644 --- a/oar-ocr-vl/src/mineru/model.rs +++ b/oar-ocr-vl/src/mineru/model.rs @@ -62,8 +62,8 @@ impl MinerUTaskPrompt { /// Map an OAR `LayoutElementType` to the MinerU element prompt that best /// matches its content kind. Mirrors the mapping the official `mineru_vl_utils` - /// client uses when picking a per-block prompt (text-like → `[default]`, - /// table → `table`, equation → `equation`, image/chart → `image`). + /// client uses when picking a per-block prompt (`[default]` for text-like blocks, + /// `table` for tables, `equation` for equations, and `image` for images and charts). pub fn for_layout(t: LayoutElementType) -> Self { use LayoutElementType::*; match t { diff --git a/oar-ocr-vl/src/paddleocr_vl/model.rs b/oar-ocr-vl/src/paddleocr_vl/model.rs index 4591bb9..5a4321d 100644 --- a/oar-ocr-vl/src/paddleocr_vl/model.rs +++ b/oar-ocr-vl/src/paddleocr_vl/model.rs @@ -605,7 +605,7 @@ impl PaddleOcrVl { } /// Decode tokens **without** applying PaddleOCR-VL's task-specific - /// post-process (OTSL→HTML for tables, `$$..$$` stripping for formulas). + /// post-process (OTSL-to-HTML for tables, `$$..$$` stripping for formulas). /// This is the raw pre-postprocess string the model actually emitted — /// use this when feeding PaddleOCR-VL output as a draft for another /// target VLM. DSV matches at token granularity, so any post-process on diff --git a/oar-ocr-vl/src/utils.rs b/oar-ocr-vl/src/utils.rs index 3da52be..2a7108e 100644 --- a/oar-ocr-vl/src/utils.rs +++ b/oar-ocr-vl/src/utils.rs @@ -24,11 +24,11 @@ use std::collections::HashSet; /// /// # Supported formats /// -/// - `"cpu"` → CPU device -/// - `"cuda"` or `"gpu"` → CUDA device 0 -/// - `"cuda:N"` → CUDA device N (e.g., `"cuda:1"`) -/// - `"metal"` → Metal device 0 (Apple GPU) -/// - `"metal:N"` → Metal device N (e.g., `"metal:1"` for Mac Pro with multiple GPUs) +/// - `"cpu"` selects the CPU device +/// - `"cuda"` or `"gpu"` selects CUDA device 0 +/// - `"cuda:N"` selects CUDA device N (e.g., `"cuda:1"`) +/// - `"metal"` selects Metal device 0 (Apple GPU) +/// - `"metal:N"` selects Metal device N (e.g., `"metal:1"` for Mac Pro with multiple GPUs) /// /// # Errors /// diff --git a/oar-ocr-vl/src/utils/table.rs b/oar-ocr-vl/src/utils/table.rs index 0dda832..dd89292 100644 --- a/oar-ocr-vl/src/utils/table.rs +++ b/oar-ocr-vl/src/utils/table.rs @@ -20,7 +20,7 @@ const OTSL_XCEL: &str = ""; /// (``, ``, ``, ``, ``, ``) which the /// model's post-process then translates into HTML. To feed an HTML-shaped /// table (e.g. from a layout pipeline) back into PaddleOCR-VL's token form we -/// need the inverse: HTML → OTSL. +/// need the inverse conversion from HTML to OTSL. /// /// The parser is intentionally tolerant — it uses regex-based extraction /// rather than a full HTML parser and mirrors `clean_html_table`'s repair of @@ -630,7 +630,7 @@ mod tests { #[test] fn convert_html_to_otsl_colspan_emits_lcel() { - // Row 1: A → A + // Row 1 converts A to A. let html = "
A
xy
"; let otsl = convert_html_to_otsl(html).expect("conversion"); assert_eq!(otsl, "Axy"); @@ -701,7 +701,7 @@ mod tests { #[test] fn convert_html_to_otsl_roundtrips_through_otsl_to_html() { - // OTSL → HTML → OTSL should reconstruct the same OTSL for a simple + // An OTSL-to-HTML-to-OTSL round trip should reconstruct the same OTSL for a simple // grid (modulo whitespace handling). This guards against drift between // the two converters. let otsl_in = "abcd"; diff --git a/src/oarocr/result.rs b/src/oarocr/result.rs index e4ebaf6..0e8eeb1 100644 --- a/src/oarocr/result.rs +++ b/src/oarocr/result.rs @@ -25,7 +25,7 @@ pub use oar_ocr_core::domain::TextRegion; /// - Bounding boxes have been **automatically transformed back** to the original coordinate system /// - You can safely overlay boxes on `input_img` for visualization /// -/// ## Rectification (Document Unwarping) +/// ## Document Rectification /// - If `rectified_img` is set, neural network-based rectification (UVDoc) was applied /// - **Limitation**: UVDoc doesn't provide inverse transformations from rectified to distorted coordinates /// - Bounding boxes are in the **rectified image's coordinate system**, not the original distorted image diff --git a/src/oarocr/stitching.rs b/src/oarocr/stitching.rs index 4d9fab2..7818f76 100644 --- a/src/oarocr/stitching.rs +++ b/src/oarocr/stitching.rs @@ -962,7 +962,7 @@ impl ResultStitcher { // --- Sort cells into rows --- // Sort structure cells — their bboxes drive both IoA matching and the - // td→cell text-assignment step. Detected-cell bboxes (cell_bboxes_override) + // td-to-cell text-assignment step. Detected-cell bboxes (cell_bboxes_override) // are intentionally NOT used for IoA because the detected model can produce // a different cell count per row than the structure tokens, causing local_idx // to diverge from td_index and corrupting OCR-to-cell assignments. @@ -983,7 +983,7 @@ impl ResultStitcher { } // Align structure-cell row flags with structure-token row boundaries. - // cell_aligned is used both for IoA matching (correct space) and td→cell mapping. + // cell_aligned is used both for IoA matching (correct space) and td-to-cell mapping. let mut cell_aligned = Self::map_and_get_max(&cell_row_flags, &row_start_index); cell_aligned.push(cell_sorted_indices.len()); row_start_index.push( @@ -993,7 +993,7 @@ impl ResultStitcher { .count(), ); - // --- Per-row matching: cell → OCR (PaddleX style) --- + // --- Per-row matching between cells and OCR results (PaddleX style) --- // For each cell in the row, collect ALL OCR boxes with IoA > 0.7. // When using detected cell bboxes (cell_bboxes_override is Some), apply // cross-row deduplication: an OCR box already claimed by an earlier row is @@ -1912,10 +1912,10 @@ impl ResultStitcher { if !ends_with_non_break_punct && right_gap > container_width * paragraph_gap_ratio { - // Previous line ended far from the right edge → paragraph break. + // A previous line ending far from the right edge starts a paragraph break. add_newline = true; } else { - // Previous line extends close to the right edge → line wrap. + // A previous line extending close to the right edge indicates a line wrap. is_line_wrap = true; } } @@ -1928,7 +1928,7 @@ impl ResultStitcher { // at line-wrap boundaries. let prev_ends_hyphen = result.ends_with('-'); if prev_ends_hyphen && is_line_wrap { - // Line wraps at hyphen → word-break hyphen, remove it + // Remove a word-break hyphen when the line wraps at that hyphen. result.pop(); // Don't add any separator - words should be joined } else if add_newline {