rusto-rs 0.1.6

RustO! - Pure Rust OCR library based on RapidOCR with PaddleOCR engine
docs.rs failed to build rusto-rs-0.1.6
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

RustO! ๐Ÿฆ€

Pure Rust OCR Library - Fast, Safe, and Cross-Platform

Crates.io NuGet npm CocoaPods Maven Central Documentation License: MIT CI

RustO! is a high-performance OCR (Optical Character Recognition) library written in pure Rust, based on RapidOCR and powered by PaddleOCR models with MNN inference engine.

๐ŸŽฏ Why RustO!?

  • ๐Ÿš€ Pure Rust - Zero OpenCV dependency, optional OpenCV backend available
  • ๐ŸŽฏ High Accuracy - 99.3% parity with OpenCV-based implementations
  • โšก Fast Performance - Optimized with LTO, single codegen unit compilation
  • ๐Ÿ”’ Memory Safe - Leverages Rust's safety guarantees
  • ๐ŸŒ Cross-Platform - Linux, macOS, Windows, iOS, Android support
  • ๐Ÿ”ง FFI Ready - C FFI bindings for integration with other languages
  • ๐Ÿ“ฆ Easy to Use - Simple API, modern CLI with JSON/Text/TSV output

๐Ÿ—๏ธ Architecture

RustO! is built on top of proven OCR technology:

  • Based on: RapidOCR architecture
  • Models: PaddleOCR PP-OCRv6 (Default), PP-OCRv5, PP-OCRv4, and PP-OCRv3 models
  • Inference: MNN inference engine for high-performance cross-platform execution on mobile, desktop, and server
  • Image Processing: Pure Rust implementation (image + imageproc crates)
  • Contour Detection: Custom Rust implementation matching OpenCV behavior

๐Ÿ“ Project Structure

rusto-rs/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ lib.rs          # Public API & exports
โ”‚   โ”œโ”€โ”€ config.rs       # RustOConfig, presets (PPV6, PPV5, PPV4, PPV3), & builders
โ”‚   โ”œโ”€โ”€ main.rs         # CLI application
โ”‚   โ”œโ”€โ”€ ffi.rs          # C FFI bindings
โ”‚   โ”œโ”€โ”€ det.rs          # Text detection (DBNet)
โ”‚   โ”œโ”€โ”€ rec.rs          # Text recognition (CTC)
โ”‚   โ”œโ”€โ”€ orient.rs       # Document orientation classification
โ”‚   โ”œโ”€โ”€ layout.rs       # Layout detection
โ”‚   โ”œโ”€โ”€ table.rs        # Table recognition & HTML structure
โ”‚   โ”œโ”€โ”€ doc_pipeline.rs # Document pipeline (layout + OCR)
โ”‚   โ”œโ”€โ”€ preprocess.rs   # Image preprocessing
โ”‚   โ”œโ”€โ”€ postprocess.rs  # Result postprocessing
โ”‚   โ”œโ”€โ”€ contours.rs     # Pure Rust contour detection
โ”‚   โ”œโ”€โ”€ geometry.rs     # Geometric transformations + NMS
โ”‚   โ”œโ”€โ”€ image_impl.rs   # Image abstraction layer
โ”‚   โ””โ”€โ”€ types.rs        # Type definitions, Frame, & Config structures
โ”œโ”€โ”€ models/
โ”‚   โ”œโ”€โ”€ PPOCR_v6/       # PP-OCRv6 MNN models (Tiny prebundled, Small, Medium)
โ”‚   โ””โ”€โ”€ PPOCR_v5/       # PP-OCRv5 MNN models
โ”œโ”€โ”€ packages/
โ”‚   โ”œโ”€โ”€ react-native/   # React Native TypeScript + iOS/Android bindings
โ”‚   โ”œโ”€โ”€ android/        # Android library (Kotlin/JNI)
โ”‚   โ”œโ”€โ”€ ios/            # iOS Swift package / CocoaPod
โ”‚   โ””โ”€โ”€ dotnet/         # .NET C# NuGet package
โ””โ”€โ”€ ...

Quick Start

1. Build the Library

# Pure Rust build (default)
cargo build --release

# With FFI bindings
cargo build --release --features ffi

# With OpenCV backend (optional)
cargo build --release --features use-opencv

2. Run CLI Application

# JSON output (default)
cargo run --release -- \
  --det-model models/PPOCR_v6/det.mnn \
  --rec-model models/PPOCR_v6/rec.mnn \
  --dict models/PPOCR_v6/dict.txt \
  image.jpg

# Plain text output
cargo run --release -- \
  --det-model models/PPOCR_v6/det.mnn \
  --rec-model models/PPOCR_v6/rec.mnn \
  --dict models/PPOCR_v6/dict.txt \
  --format text \
  image.jpg

# TSV output
cargo run --release -- \
  --det-model models/PPOCR_v6/det.mnn \
  --rec-model models/PPOCR_v6/rec.mnn \
  --dict models/PPOCR_v6/dict.txt \
  --format tsv \
  image.jpg

3. Use as a Rust Library

Add to your Cargo.toml:

[dependencies]
rusto = "0.1"

Then in your code:

use rusto::{RustO, RustOConfig};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Configure OCR with default PP-OCRv6 preset
    let config = RustOConfig::new(
        "models/PPOCR_v6/det.mnn",
        "models/PPOCR_v6/rec.mnn",
        "models/PPOCR_v6/dict.txt",
    )
    .with_text_score(0.5)
    .with_xy_threshold(0.5, 1.0); // Configure spatial text spacing
    
    // Create OCR instance
    let mut ocr = RustO::new(config)?;
    
    // Run OCR on an image
    let output = ocr.run("image.jpg")?;
    
    // 1. Get structured text results with axis-aligned bounding frames
    let results = output.to_text_results();
    for res in results {
        println!("Text: '{}' (Score: {:.2})", res.text, res.score);
        println!("  Frame: left={:.1}, top={:.1}, w={:.1}, h={:.1}", 
            res.frame.left, res.frame.top, res.frame.width, res.frame.height);
        println!("  Polygon: {:?}", res.box_points);
    }
    
    // 2. Reconstruct spatial document layout text
    let spatial_text = output.to_spatial_text(None, None);
    println!("Spatial Layout:\n{}", spatial_text);
    
    Ok(())
}

4. Template Presets & Architecture Support

RustO! provides pre-configured template presets for different PaddleOCR model generations:

use rusto::{RustOConfig, PPV6_MODEL_CONFIG, PPV5_MODEL_CONFIG, PPV4_MODEL_CONFIG, PPV3_MODEL_CONFIG};

// PP-OCRv6 (Default): limit_side_len=736, min, det_thresh=0.3, det_box_thresh=0.6, unclip=2.0
let v6_config = RustOConfig::ppv6("det.mnn", "rec.mnn", "dict.txt");

// PP-OCRv5: limit_side_len=736, min, det_thresh=0.3, det_box_thresh=0.5, unclip=2.0
let v5_config = RustOConfig::ppv5("det.mnn", "rec.mnn", "dict.txt");

// PP-OCRv4: limit_side_len=960, max, det_thresh=0.3, det_box_thresh=0.6, unclip=1.5
let v4_config = RustOConfig::ppv4("det.mnn", "rec.mnn", "dict.txt");

// PP-OCRv3: limit_side_len=960, max, det_thresh=0.3, det_box_thresh=0.6, unclip=1.5
let v3_config = RustOConfig::ppv3("det.mnn", "rec.mnn", "dict.txt");

5. Cross-Platform SDKs

React Native

import { initialize, detectText, detectTextToSpatialText } from 'react-native-rusto';

// Initialize with bundled default PP-OCRv6 tiny models (no parameters needed!)
await initialize();

// Detect text with bounding frames
const results = await detectText('/path/to/image.jpg');
results.forEach((r) => {
  console.log(`${r.text} (${r.score}) - Frame:`, r.frame); // { width, height, top, left }
});

// Or format directly to spatial layout text
const spatialText = await detectTextToSpatialText('/path/to/image.jpg', 0.5, 1.0);
console.log(spatialText);

iOS (Swift)

import RustO

// Default PP-OCRv6 configuration
let config = RustOConfig.ppv6(
    det: "det.mnn",
    rec: "rec.mnn",
    dict: "dict.txt"
)
let ocr = try RustO(config: config)

let results = try ocr.recognizeFile("image.jpg")
for result in results {
    print("\(result.text) (\(result.score)): frame=\(result.frame.left),\(result.frame.top),\(result.frame.width)x\(result.frame.height)")
}

Android (Kotlin)

import com.byrizki.rusto.RustO
import com.byrizki.rusto.RustOConfig

val config = RustOConfig(
    template = "ppv6",
    detModelPath = "det.mnn",
    recModelPath = "rec.mnn",
    dictPath = "dict.txt"
)
val ocr = RustO(context, config)
val results = ocr.recognizeFile("/path/to/image.jpg")

.NET (C#)

using RustODotnet;

var config = RustOConfig.Ppv6("det.mnn", "rec.mnn", "dict.txt");
using var ocr = new RustO(config);
var results = ocr.RecognizeFile("image.jpg");

API Reference

RustOConfig & Builders

Comprehensive configuration structure supporting granular parameter overrides:

let config = RustOConfig::ppv6("det.mnn", "rec.mnn", "dict.txt")
    // Detection tuning
    .with_det_thresh(0.3)
    .with_det_box_thresh(0.6)
    .with_limit_side_len(736)
    .with_limit_type("min")
    .with_unclip_ratio(2.0)
    .with_use_dilation(true)
    .with_max_candidates(1000)
    .with_score_mode("fast")
    // Recognition tuning
    .with_rec_img_shape([3, 48, 320])
    .with_rec_batch_num(6)
    // Global & Spatial tuning
    .with_text_score(0.5)
    .with_xy_threshold(0.5, 1.0)
    .with_min_height(30.0)
    .with_max_side_len(2000.0)
    // Optional modules
    .with_cls("models/cls.mnn", 0.9)
    .with_orientation("models/orient.mnn", 0.9)
    .with_unwarp("models/unwarp.mnn");

Frame & TextResult

pub struct Frame {
    pub width: f32,
    pub height: f32,
    pub top: f32,
    pub left: f32,
}

pub struct TextResult {
    pub text: String,                    // Recognized text string
    pub score: f32,                      // Confidence score (0.0 - 1.0)
    pub box_points: [(f32, f32); 4],    // 4 rotated polygon corner points
    pub frame: Frame,                    // Axis-aligned bounding frame
}

๐Ÿ“ฆ Models

RustO! uses lightweight, high-performance PaddleOCR models in MNN format:

Model Series Supported

  • PP-OCRv6 (Default & Recommended) โ€” MetaFormer-based PPLCNetV4 architecture with 50-language unified dictionary. Available in Tiny (prebundled, 6.0 MB total), Small, and Medium tiers.
  • PP-OCRv5 โ€” High-accuracy detection with SVTR-LCNet recognition.
  • PP-OCRv4 โ€” Lightweight mobile OCR models.
  • PP-OCRv3 โ€” Legacy mobile OCR models.

Downloading Pre-Converted MNN Models

Official models are hosted on ModelScope RapidAI/RapidOCR:

# PP-OCRv6 Tiny (Prebundled default)
curl -L -o models/PPOCR_v6/det.mnn "https://www.modelscope.cn/api/v1/models/RapidAI/RapidOCR/repo?Revision=master&FilePath=mnn%2FPP-OCRv6%2Fdet%2FPP-OCRv6_det_tiny.mnn"
curl -L -o models/PPOCR_v6/rec.mnn "https://www.modelscope.cn/api/v1/models/RapidAI/RapidOCR/repo?Revision=master&FilePath=mnn%2FPP-OCRv6%2Frec%2FPP-OCRv6_rec_tiny.mnn"
curl -L -o models/PPOCR_v6/dict.txt "https://www.modelscope.cn/api/v1/models/RapidAI/RapidOCR/repo?Revision=master&FilePath=paddle%2FPP-OCRv6%2Frec%2FPP-OCRv6_rec_tiny%2Fppocrv6_tiny_dict.txt"

๐Ÿ”Œ C FFI & Shared Libraries

RustO! provides a high-performance C FFI interface for building desktop, mobile, and native bindings. Enable with the ffi feature:

cargo build --release --features ffi

This compiles shared libraries:

  • Linux: target/release/librusto.so
  • macOS / iOS: target/release/librusto.dylib
  • Windows: target/release/rusto.dll

FFI APIs include rocr_new_with_config(config_json), rocr_run(inst, image_path), rocr_run_to_spatial_text(inst, image_path, y_multiplier, x_multiplier), and direct memory pointer interfaces.


โšก Performance

Benchmarks

Tested on typical document images:

Metric Value
Detection ~80ms
Recognition (per box) ~120ms
Total (28 boxes) ~3.5s
Memory Peak ~200MB

Comparison with OpenCV-based implementations

Aspect RustO! OpenCV-based
Speed โœ… Similar (ยฑ10%) Baseline
Accuracy โœ… 99.3% parity 100%
Binary Size โœ… Smaller Larger (OpenCV deps)
Memory Usage โœ… Lower Higher (OpenCV overhead)
Dependencies โœ… Minimal OpenCV required
Safety โœ… Memory safe Manual memory management

Configuration

Cargo Features

[features]
default = []           # Pure Rust mode
use-opencv = ["opencv"] # Use OpenCV backend
ffi = []               # Enable C FFI bindings

Build Profiles

[profile.release]
opt-level = 3          # Maximum optimization
lto = "fat"            # Link-time optimization
codegen-units = 1      # Single codegen unit for better optimization
strip = true           # Strip symbols
panic = "abort"        # Smaller binary

Development

Run Tests

cd rapidocr
cargo test
cargo test --features use-opencv  # Test OpenCV backend

Run Benchmarks

cargo bench

Check Code

cargo clippy
cargo fmt --check

Known Issues

Rust Library (contours.rs)

  • โš ๏ธ Unused functions (400+ lines) - cleanup pending
  • โš ๏ธ Minor lint warnings - non-blocking

Remaining Parity Gap (0.7%)

  • 2 minor text differences out of 28 boxes
  • Caused by: Spacing ("Gol. Darah:" vs "Gol. Darah :")
  • Impact: Negligible for production use

License

MIT (or your license)


Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Run tests: cargo test
  5. Submit a pull request

Support

  • ๐Ÿ“ง Email: support@rapidocr.com
  • ๐Ÿ’ฌ Discussions: GitHub Discussions
  • ๐Ÿ› Issues: GitHub Issues

๐Ÿ™ Acknowledgments

RustO! builds upon the excellent work of:

  • RapidOCR - Architecture and design inspiration
  • PaddleOCR - State-of-the-art OCR models (PPOCRv4/v5)
  • ONNX Runtime - Cross-platform inference engine
  • Rust Community - Excellent tooling and libraries (image, imageproc, nalgebra)

๐Ÿ“ Citation

If you use RustO! in your research or project, please cite:

@software{rusto2024,
  title = {RustO! - Pure Rust OCR Library},
  author = {byrizki},
  year = {2024},
  url = {https://github.com/byrizki/rusto-rs},
  note = {Based on RapidOCR and powered by PaddleOCR models}
}

Also consider citing the underlying technologies:


Status: Production Ready ๐Ÿš€
Version: 0.1.6
License: MIT

Made with โค๏ธ and ๐Ÿฆ€ Rust

Report Bug ยท Request Feature ยท Contribute