ocr-rs

repository·next·Indexed 43 days ago

https://github.com/zibo-chen/rust-paddle-ocr

A lightweight and efficient Rust OCR library based on PaddleOCR models, using the MNN inference framework for high-performance text detection and recognition. Version 2.4.1 supports end-to-end OCR via OcrEngine, specialized detection-only or recognition-only engines, and hardware acceleration through CUDA, Vulkan, Metal, and OpenCL backends.

Tokens
17.8K
Snippets
62
Records
78
Agent score
55%

What's inside ocr-rs

  1. Configure GPU tuning modes and precision in OcrEngineConfig

    next

    When using GPU backends (OpenCL or Vulkan), you can control the trade-off between startup latency and steady-state throughput using GpuTuningMode and precision settings via OcrEngineConfig.

    Tuning Modes

    • GpuTuningMode::Auto: The default. Selects FAST for OpenCL and NONE for Vulkan. This reduces tuning work during cold or dynamic inference but may trade off some throughput for lower startup latency.
    • GpuTuningMode::Wide and GpuTuningMode::Heavy: Explicit options for fixed-shape, long-running workloads where maximum throughput is required.

    Precision and Backends

    • OpenCL: Retains Buffer memory support.
    • Vulkan: Does not support OpenCL-only Fast/Normal tuning modes.
    • Precision Mapping: For Vulkan, OcrEngineConfig maps Normal precision to High precision. This is because MNN 3.6.1's Vulkan buffer backend defaults to fp16 unless High is requested. High precision is recommended for long recognition sequences to mitigate numerical issues. Low precision is also explicitly supported.
    // Example of configuring tuning and precision
    let config = OcrEngineConfig::new()
        .with_gpu_tuning(GpuTuningMode::Wide)
        .with_precision(Precision::High);
  2. Handle mixed horizontal and vertical text with Robust mode

    next

    By default, recognize follows standard detection behavior. If your image contains both horizontal text and text rotated by 90° or 270° (vertical text), you should use recognize_with_options with RotatedTextMode::Robust.

    RotatedTextMode::Robust performs additional detection for rotated text, maps the found bounding boxes back to the input image coordinates, and recognizes only the vertical candidates.

    If the standard detection already finds the vertical boxes, you can use RotatedTextMode::DetectedOnly to reduce overhead.

    use ocr_rs::{RecognizeOptions, RotatedTextMode};
    
    let options = RecognizeOptions::new()
        .with_rotated_text_mode(RotatedTextMode::Robust);
    let results = engine.recognize_with_options(&image, &options)?;
  3. Build with GPU features and MNN from source

    next

    By default, the project uses pre-built MNN for CPU or Apple Metal. To enable GPU acceleration via CUDA or Vulkan, or to build MNN from source, use the following cargo commands:

    # Build MNN from source
    cargo build --features build-mnn-from-source
    
    # Enable CUDA
    cargo build --release --features cuda
    
    # Enable Vulkan
    cargo build --release --features vulkan

    Note: You must have the appropriate SDK and development libraries installed for the chosen backend before building.

  4. Convert Paddle models to MNN format

    next

    Use the provided Python script to convert Paddle inference models to MNN format. The script enables MNN FP16 by default to reduce model size. Use --install-dir to copy the converted files to your target directory.

    python script/convert_paddle_to_mnn.py \
      --ocr-dir /path/to/paddle/inference/models \
      --install-dir ./models

    Use --no-fp16 only if you require full-precision MNN output.

  5. Build with specific features (CUDA, Vulkan, MNN source)

    next

    You can control how the library and its dependencies are built using Cargo features:

    • Build MNN from source: cargo build --features build-mnn-from-source
    • CUDA support: cargo build --release --features cuda
    • Vulkan support: cargo build --release --features vulkan
    • Static C++ runtime (Windows/MinGW): To avoid dependencies on MinGW DLLs on Windows, use --features static-cpp-runtime.
    # Example: Building for CUDA on Windows (MSVC target)
    cargo build --release --target x86_64-pc-windows-msvc --features cuda
    
    # Example: Building with static C++ runtime for MinGW
    cargo build --release --target x86_64-pc-windows-gnu --features static-cpp-runtime
  6. Use the ocr-rs library in Rust

    next

    To perform OCR, initialize an OcrEngine with paths to your detection model, recognition model, and character keys file. You can then use the .recognize() method on an image to get text results and confidence scores.

    If you only need specific parts of the pipeline, you can use det_only or rec_only to save resources.

    use ocr_rs::OcrEngine;
    
    fn main() -> Result<(), Box<dyn std::error::Error>> {
        // Full End-to-End OCR
        let engine = OcrEngine::new(
            "models/PP-OCRv6_small_det.mnn",
            "models/PP-OCRv6_small_rec.mnn",
            "models/ppocr_keys_v6_small.txt",
            None,
        )?;
    
        let image = image::open("test.jpg")?;
        let results = engine.recognize(&image)?;
    
        for item in results {
            println!("{:.2}: {}", item.confidence, item.text);
        }
    
        Ok(())
    }
    
    // Detection only
    let det = ocr_rs::OcrEngine::det_only("models/PP-OCRv6_small_det.mnn", None)?;
    
    // Recognition only
    let rec = ocr_rs::OcrEngine::rec_only(
        "models/PP-OCRv6_small_rec.mnn",
        "models/ppocr_keys_v6_small.txt",
        None,
    )?;
  7. Build for Windows (x86_64-pc-windows-gnu) with static runtime

    next

    When targeting x86_64-pc-windows-gnu, MNN is built from source and requires a MinGW C/C++ toolchain. To avoid distributing MinGW runtime DLLs with your binary, use the static-cpp-runtime feature to statically link libstdc++, libgcc, and winpthreads.

    cargo build --release --target x86_64-pc-windows-gnu --features static-cpp-runtime
  8. Convert Paddle Models to MNN

    next

    Use the provided Python script to convert Paddle inference models to MNN format. The script uses MNN FP16 by default to reduce model size. Use --install-dir ./models to copy the converted models to the standard directory used by the Rust runtime.

    To use full precision instead of FP16, add the --no-fp16 flag.

    python script/convert_paddle_to_mnn.py \
      --ocr-dir /path/to/paddle/inference/models \
      --install-dir ./models
  9. Enable persistent GPU kernel caches

    next

    To avoid slow shader compilation and tuning during every session, you can enable persistent kernel caches. This allows MNN to load cached kernels before session creation.

    Implementation

    Use .with_gpu_cache_dir("PATH") on your OcrEngineConfig to specify a directory for the caches.

    Best Practices

    • Cache Uniqueness: Cache filenames are unique to the specific model bytes (SHA-256), MNN version, backend, precision, tuning, and memory configuration. Detection and recognition caches are stored separately.
    • Persistence: While engine destruction attempts to save the cache, it cannot report write failures. For critical persistence, explicitly call InferenceEngine::save_cache() after a warmup session.
    • Environment: Keep caches local to a single device/driver environment. Clear the cache directory after performing GPU driver upgrades.
    • Concurrency: Do not share cache writes between concurrent processes.
    use ocr_rs::{Backend, OcrEngineConfig};
    
    let config = OcrEngineConfig::new()
        .with_backend(Backend::OpenCL)
        .with_gpu_cache_dir(".cache/ocr-gpu");
  10. Run performance benchmarks and smoke tests

    next

    To check local performance, use the Criterion-based benchmarks:

    cargo bench --bench bench_metrics

    To run CI-style performance smoke tests (which compare against regression limits):

    OCR_RS_PERF_TESTS=1 cargo test --release --test performance_tests -- --nocapture --test-threads=1
  11. Build for Windows (MinGW/MSVC)

    next

    MinGW (x86_64-pc-windows-gnu)

    Building for MinGW requires the MinGW C/C++ toolchain. You must distribute the matching MinGW runtime DLLs with your application. To avoid DLL dependencies, you can statically link the C++ runtime using the static-cpp-runtime feature:

    cargo build --release --target x86_64-pc-windows-gnu --features static-cpp-runtime

    MSVC (x86_64-pc-windows-msvc)

    NVIDIA Windows CUDA toolchains require MSVC. For CUDA source builds, use the x86_64-pc-windows-msvc target or provide compatible MNN libraries via mnn-dynamic/mnn-static.