ocr-rs 2.2.2

A lightweight and efficient OCR library based on PaddleOCR models, using the MNN inference framework for high-performance text detection and recognition
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
# Rust PaddleOCR

[English](../README.md) | [中文](README.zh.md) | [日本語](README.ja.md) | [한국어](README.ko.md)

一个基于PaddleOCR模型的轻量级高效OCR(光学字符识别)Rust库。该库利用MNN推理框架提供高性能的文本检测和识别功能。

**本项目是纯Rust库**,专注于提供OCR核心功能。如需命令行工具或其他语言绑定,请参考:
- 🖥️ **命令行工具**:[newbee-ocr-cli](https://github.com/zibo-chen/newbee-ocr-cli)
- 🔌 **C API绑定**:[paddle-ocr-capi](https://github.com/zibo-chen/paddle-ocr-capi) - 提供C API以方便与其他编程语言集成
- 🌐 **HTTP服务**:[newbee-ocr-service](https://github.com/zibo-chen/newbee-ocr-service) ⚠️ (施工中)

[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)

## ✨ 版本 2.0 新特性

- 🎯 **全新分层 API 设计**:提供从底层模型到高层 Pipeline 的完整分层 API
- 🔧 **灵活的模型加载**:支持从文件路径或内存字节加载模型
- ⚙️ **可配置的检测参数**:支持自定义检测阈值、分辨率、精度模式等
- 🚀 **GPU 加速支持**:支持 Metal、OpenCL、Vulkan 等多种 GPU 后端
- 📦 **批量处理优化**:支持批量文本识别以提高吞吐量
- 🔌 **独立引擎模式**:可以只创建检测引擎或识别引擎

## 特性

### 核心功能
- **文本检测**:准确定位图像中的文本区域
- **文本识别**:识别检测区域中的文本内容
- **端到端识别**:一次调用完成检测和识别全流程
- **分层 API 架构**:支持端到端、分层调用和独立模型三种使用方式

### 模型支持
- **多版本模型支持**:支持 PP-OCRv4 和 PP-OCRv5 模型,灵活选择使用
- **多语言支持**:PP-OCRv5 支持11+种专用语言模型,覆盖100+种语言
- **复杂场景识别**:增强的手写体、竖排文本、生僻字识别能力
- **灵活加载方式**:支持从文件路径或内存字节加载模型

### 性能特性
- **高性能推理**:基于 MNN 推理框架,速度快、内存占用低
- **GPU 加速**:支持 Metal、OpenCL、Vulkan 等多种 GPU 后端
- **批量处理**:支持批量文本识别,提高吞吐量

### 开发体验
- **灵活配置**:检测阈值、分辨率、精度模式等参数均可自定义
- **内存安全**:自动内存管理,防止内存泄漏
- **纯 Rust 实现**:无需外部运行时,跨平台兼容
- **最小依赖**:轻量级且易于集成

## 模型版本

该库支持三个PaddleOCR模型版本:

### PP-OCRv4
- **稳定版本**:经过充分验证,兼容性好
- **适用场景**:常规文档识别,对准确性要求较高的场景
- **模型文件**:
  - 检测模型:`ch_PP-OCRv4_det_infer.mnn`
  - 识别模型:`ch_PP-OCRv4_rec_infer.mnn`
  - 字符集:`ppocr_keys_v4.txt`

### PP-OCRv5
- **最新版本**:新一代文字识别解决方案
- **多语言支持**:默认模型(`PP-OCRv5_mobile_rec.mnn`)支持简体中文、繁体中文、英文、日文、中文拼音
- **专用语言模型**:提供11+种语言的专用模型,覆盖100+种语言,以获得最佳性能
- **共享检测模型**:所有V5语言模型使用相同的检测模型(`PP-OCRv5_mobile_det.mnn`)
- **增强场景识别**:
  - 中英复杂手写体识别能力显著提升
  - 竖排文本识别优化
  - 生僻字识别能力增强
- **性能提升**:相比PP-OCRv4端到端提升13个百分点
- **模型文件**(默认多语言):
  - 检测模型:`PP-OCRv5_mobile_det.mnn`(所有语言共享)
  - 识别模型:`PP-OCRv5_mobile_rec.mnn`(默认,支持中文/英文/日文)
  - 字符集:`ppocr_keys_v5.txt`
- **专用语言模型文件**(可选):
  - 识别模型:`{lang}_PP-OCRv5_mobile_rec_infer.mnn`
  - 字符集:`ppocr_keys_{lang}.txt`
  - 可用语言代码:`arabic`、`cyrillic`、`devanagari`、`el`、`en`、`eslav`、`korean`、`latin`、`ta`、`te`、`th`

#### PP-OCRv5 语言模型详细支持列表

| 模型名称 | 支持的语言 |
|---------|-----------|
| **korean_PP-OCRv5_mobile_rec** | 韩语、英语 |
| **latin_PP-OCRv5_mobile_rec** | 法语、德语、南非荷兰语、意大利语、西班牙语、波斯尼亚语、葡萄牙语、捷克语、威尔士语、丹麦语、爱沙尼亚语、爱尔兰语、克罗地亚语、乌兹别克语、匈牙利语、塞尔维亚语(拉丁字母)、印度尼西亚语、奥克语、冰岛语、立陶宛语、毛利语、马来语、荷兰语、挪威语、波兰语、斯洛伐克语、斯洛文尼亚语、阿尔巴尼亚语、瑞典语、斯瓦希里语、他加禄语、土耳其语、拉丁语、阿塞拜疆语、库尔德语、拉脱维亚语、马耳他语、巴利语、罗马尼亚语、越南语、芬兰语、巴斯克语、加利西亚语、卢森堡语、罗曼什语、加泰罗尼亚语、克丘亚语 |
| **eslav_PP-OCRv5_mobile_rec** | 俄语、白俄罗斯语、乌克兰语、英语 |
| **th_PP-OCRv5_mobile_rec** | 泰语、英语 |
| **el_PP-OCRv5_mobile_rec** | 希腊语、英语 |
| **en_PP-OCRv5_mobile_rec** | 英语 |
| **cyrillic_PP-OCRv5_mobile_rec** | 俄语、白俄罗斯语、乌克兰语、塞尔维亚语(西里尔字母)、保加利亚语、蒙古语、阿布哈兹语、阿迪格语、卡巴尔达语、阿瓦尔语、达尔金语、印古什语、车臣语、拉克语、列兹金语、塔巴萨兰语、哈萨克语、吉尔吉斯语、塔吉克语、马其顿语、鞑靼语、楚瓦什语、巴什基尔语、马里语、摩尔多瓦语、乌德穆尔特语、科米语、奥塞梯语、布里亚特语、卡尔梅克语、图瓦语、萨哈语、卡拉卡尔帕克语、英语 |
| **arabic_PP-OCRv5_mobile_rec** | 阿拉伯语、波斯语、维吾尔语、乌尔都语、普什图语、库尔德语、信德语、俾路支语、英语 |
| **devanagari_PP-OCRv5_mobile_rec** | 印地语、马拉地语、尼泊尔语、比哈尔语、迈蒂利语、昂加语、博杰普尔语、摩揭陀语、桑塔利语、尼瓦尔语、孔卡尼语、梵语、哈里亚纳语、英语 |
| **ta_PP-OCRv5_mobile_rec** | 泰米尔语、英语 |
| **te_PP-OCRv5_mobile_rec** | 泰卢固语、英语 |

### PP-OCRv5 FP16
- **高效版本**:在不牺牲准确率的情况下提供更快的推理速度和更低的内存使用
- **适用场景**:需要高性能和低内存使用的场景
- **性能提升**:
  - 推理速度提升约9% (支持FP16推理加速的设备上性能会更高)
  - 内存使用减少约8%
  - 模型大小减半
- **模型文件**:
  - 检测模型:`PP-OCRv5_mobile_det_fp16.mnn`
  - 识别模型:`PP-OCRv5_mobile_rec_fp16.mnn`
  - 字符集:`ppocr_keys_v5.txt`

### 模型性能对比

| 特性               | PP-OCRv4 | PP-OCRv5 | PP-OCRv5 FP16 |
|--------------------|----------|----------|---------------|
| 语言支持           | 中文、英文 | 多语言(默认支持中文/英文/日文,提供11+种专用语言模型) | 多语言(默认支持中文/英文/日文,提供11+种专用语言模型) |
| 文字类型支持       | 中文、英文 | 简体中文、繁体中文、英文、日文、中文拼音 | 简体中文、繁体中文、英文、日文、中文拼音 |
| 手写体识别         | 基础支持  | 显著增强  | 显著增强       |
| 竖排文本           | 基础支持  | 优化提升  | 优化提升       |
| 生僻字识别         | 有限支持  | 增强识别  | 增强识别       |
| 推理速度 (FPS)     | 1.1      | 1.2      | 1.2           |
| 内存使用 (峰值)    | 422.22MB | 388.41MB | 388.41MB      |
| 模型大小           | 标准      | 标准      | 减半           |
| 推荐场景           | 常规文档  | 复杂场景与多语言 | 高性能场景与多语言 |

## 应用场景

根据不同的使用需求,选择合适的 API 层级:

### 场景 1:快速集成 OCR 功能
**使用:端到端识别(OcrEngine)**

适合:
- 快速原型开发
- 简单的文档识别需求
- 不需要中间处理步骤
- 只关心最终文本结果

```rust
let engine = OcrEngine::new(det_path, rec_path, charset_path, None)?;
let results = engine.recognize(&image)?;
```

### 场景 2:需要自定义检测后处理
**使用:分层调用(OcrEngine 的 detect + recognize_batch)**

适合:
- 需要过滤或筛选检测结果
- 需要调整文本框位置
- 需要按特定顺序处理文本
- 需要对检测框进行排序或分组

```rust
let engine = OcrEngine::new(det_path, rec_path, charset_path, None)?;
// 1. 检测
let mut boxes = engine.detect(&image)?;
// 2. 自定义处理(如过滤小框)
boxes.retain(|b| b.rect.width() > 50);
// 3. 识别
let detections = engine.det_model().detect_and_crop(&image)?;
let results = engine.recognize_batch(&images)?;
```

### 场景 3:只需要检测功能
**使用:DetOnlyEngine**

适合:
- 文档版面分析
- 文本区域标注工具
- 预处理流程(只需要知道文本位置)
- 与其他识别引擎配合使用

```rust
let det_engine = OcrEngine::det_only("models/det_model.mnn", None)?;
let text_boxes = det_engine.detect(&image)?;
// 使用检测框做其他处理...
```

### 场景 4:只需要识别功能
**使用:RecOnlyEngine**

适合:
- 已知文本位置,只需要识别
- 处理预先裁剪好的文本行图像
- 手写体识别(输入单行文字图像)
- 批量识别固定格式的文本

```rust
let rec_engine = OcrEngine::rec_only(
    "models/rec_model.mnn",
    "models/ppocr_keys.txt",
    None
)?;
let text = rec_engine.recognize_text(&text_line_image)?;
```

### 场景 5:完全自定义流程
**使用:独立模型(DetModel + RecModel)**

适合:
- 需要自定义预处理流程
- 需要对检测和识别使用不同配置
- 需要在检测和识别之间插入复杂处理逻辑
- 性能优化(如复用检测结果)

```rust
let det_model = DetModel::from_file("models/det_model.mnn", None)?;
    
let rec_model = RecModel::from_file(
    "models/rec_model.mnn",
    "models/ppocr_keys.txt",
    None
)?;

// 完全自定义的处理流程...
```

### 场景 6:嵌入式或加密部署
**使用:从字节加载模型**

适合:
- 嵌入式设备(将模型编译进二进制)
- 需要模型加密
- 从网络动态下载模型
- 自定义模型存储格式

```rust
let det_bytes = include_bytes!("../models/det_model.mnn");
let rec_bytes = include_bytes!("../models/rec_model.mnn");
let charset_bytes = include_bytes!("../models/ppocr_keys.txt");

let engine = OcrEngine::from_bytes(det_bytes, rec_bytes, charset_bytes, None)?;
```


## 安装

在`Cargo.toml`中添加:

```toml
[dependencies.rust-paddle-ocr]
git = "https://github.com/zibo-chen/rust-paddle-ocr.git"

```

您也可以指定特定分支或标签:

```toml
[dependencies.rust-paddle-ocr]
git = "https://github.com/zibo-chen/rust-paddle-ocr.git"
branch = "main"
```

### 前提条件

该库需要:
- 转换为MNN格式的预训练PaddleOCR模型
- 用于文本识别的字符集文件

### MNN 链接方式

默认情况下,会自动从 [MNN-Prebuilds](https://github.com/zibo-chen/MNN-Prebuilds) 下载预编译的 MNN 静态库,无需安装 cmake 或 C++ 编译工具链。

支持自动下载预编译库的平台:
- Linux x86_64 / aarch64
- Windows x86_64 / i686
- macOS(通用:x86_64 + arm64)
- iOS arm64 / arm64-sim
- Android arm64-v8a / armeabi-v7a

不支持的平台会自动回退到从源码编译。

#### 强制从源码编译

如果需要自定义 MNN 编译选项(如 GPU 加速),可以强制从源码编译:

```bash
cargo build --features build-mnn-from-source
```

#### 使用预编译动态库

```bash
MNN_LIB_DIR=/path/to/mnn/lib MNN_INCLUDE_DIR=/path/to/mnn/include \
  cargo build --features mnn-dynamic
```

#### 使用预编译静态库

```bash
MNN_LIB_DIR=/path/to/mnn/lib MNN_INCLUDE_DIR=/path/to/mnn/include \
  cargo build --features mnn-static
```

#### 环境变量

| 变量 | 是否必需 | 说明 |
|---|---|---|
| `MNN_LIB_DIR` | 是(使用 `mnn-dynamic` / `mnn-static` 时) | 包含预编译 MNN 库文件的目录(`libMNN.so` / `libMNN.dylib` / `libMNN.a`) |
| `MNN_INCLUDE_DIR` | 否 | 包含 MNN 头文件的目录。未设置时回退到 `MNN_SOURCE_DIR/include` 或 `3rd_party/MNN/include` |
| `MNN_SOURCE_DIR` | 否 | MNN 源码目录(用于获取头文件或从源码编译) |

## API 架构

本库提供了**分层推理 API**,让您可以根据不同场景灵活选择使用方式:

```text
┌─────────────────────────────────────────────────┐
│         OcrEngine (端到端 Pipeline)              │
│          一次调用完成检测和识别                    │
├─────────────────────────────────────────────────┤
│  DetOnlyEngine  │  RecOnlyEngine   │  OcrEngine │
│  只做检测        │  只做识别          │  检测+识别  │
├─────────────────────────────────────────────────┤
│     DetModel          │        RecModel         │
│   文本检测模型          │       文本识别模型        │
├─────────────────────────────────────────────────┤
│            InferenceEngine (MNN)                │
│              底层推理引擎                         │
└─────────────────────────────────────────────────┘
```

### 三种使用方式

#### 1. 端到端识别(推荐)- 最简单

使用 `OcrEngine` 完成完整的 OCR 流程,一次调用完成检测和识别:

```rust
use ocr_rs::OcrEngine;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建 OCR 引擎(使用默认配置)
    let engine = OcrEngine::new(
        "models/PP-OCRv5_mobile_det.mnn",
        "models/PP-OCRv5_mobile_rec.mnn",
        "models/ppocr_keys_v5.txt",
        None,
    )?;
    
    // 加载图像
    let image = image::open("test.jpg")?;
    
    // 一次调用完成检测和识别
    let results = engine.recognize(&image)?;
    
    // 输出结果
    for result in results {
        println!("文本: {}", result.text);
        println!("置信度: {:.2}%", result.confidence * 100.0);
        println!("位置: ({}, {})", result.bbox.rect.left(), result.bbox.rect.top());
    }
    
    Ok(())
}
```

#### 2. 分层调用 - 更灵活

使用 `OcrEngine` 但分别调用检测和识别,适合需要在中间插入自定义处理的场景:

```rust
use ocr_rs::OcrEngine;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let engine = OcrEngine::new(det_path, rec_path, charset_path, None)?;
    let image = image::open("test.jpg")?;
    
    // 1. 先只做检测
    let text_boxes = engine.detect(&image)?;
    println!("检测到 {} 个文本区域", text_boxes.len());
    
    // 这里可以做一些自定义处理,比如:
    // - 过滤不需要的区域
    // - 调整检测框位置
    // - 按位置排序等
    
    // 2. 获取检测模型,手动裁剪
    let det_model = engine.det_model();
    let detections = det_model.detect_and_crop(&image)?;
    
    // 3. 批量识别裁剪后的图像
    let cropped_images: Vec<_> = detections.iter()
        .map(|(img, _)| img.clone())
        .collect();
    let rec_results = engine.recognize_batch(&cropped_images)?;
    
    for (result, (_, bbox)) in rec_results.iter().zip(detections.iter()) {
        println!("{}: {:.2}%", result.text, result.confidence * 100.0);
    }
    
    Ok(())
}
```

#### 3. 独立模型调用 - 最灵活

分别创建检测和识别引擎,或只创建单一功能引擎:

```rust
use ocr_rs::{DetModel, RecModel, DetOptions, RecOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 方式A: 分别创建检测和识别模型
    let det_model = DetModel::from_file("models/det_model.mnn", None)?;
    
    let rec_model = RecModel::from_file(
        "models/rec_model.mnn",
        "models/ppocr_keys.txt",
        None
    )?.with_options(RecOptions::new().with_min_score(0.5));
    
    let image = image::open("test.jpg")?;
    
    // 检测并裁剪
    let detections = det_model.detect_and_crop(&image)?;
    
    // 批量识别
    let images: Vec<_> = detections.iter().map(|(img, _)| img.clone()).collect();
    let results = rec_model.recognize_batch(&images)?;
    
    // 处理结果...
    
    // 方式B: 只创建检测引擎
    let det_only = OcrEngine::det_only("models/det_model.mnn", None)?;
    let text_boxes = det_only.detect(&image)?;
    
    // 方式C: 只创建识别引擎
    let rec_only = OcrEngine::rec_only(
        "models/rec_model.mnn",
        "models/ppocr_keys.txt",
        None
    )?;
    let text = rec_only.recognize_text(&cropped_image)?;
    
    Ok(())
}
```

## 使用示例

### 基本配置选项

```rust
use ocr_rs::{OcrEngine, OcrEngineConfig};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 使用快速模式配置
    let config = OcrEngineConfig::fast();
    
    let engine = OcrEngine::new(
        "models/PP-OCRv5_mobile_det.mnn",
        "models/PP-OCRv5_mobile_rec.mnn",
        "models/ppocr_keys_v5.txt",
        Some(config),
    )?;
    
    let image = image::open("test.jpg")?;
    let results = engine.recognize(&image)?;
    
    Ok(())
}
```

### GPU 加速

```rust
use ocr_rs::{OcrEngine, OcrEngineConfig, Backend};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 使用 GPU 加速
    let config = OcrEngineConfig::new()
        .with_backend(Backend::Metal);    // macOS: Metal
        // .with_backend(Backend::OpenCL); // 跨平台: OpenCL
        // .with_backend(Backend::Vulkan); // Windows/Linux: Vulkan
    
    let engine = OcrEngine::new(det_path, rec_path, charset_path, Some(config))?;
    
    Ok(())
}
```

### 自定义检测和识别参数

```rust
use ocr_rs::{OcrEngine, OcrEngineConfig, DetOptions, RecOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 自定义配置
    let config = OcrEngineConfig::new()
        .with_threads(8)
        .with_det_options(
            DetOptions::new()
                .with_max_side_len(1920)     // 更高的检测分辨率
                .with_box_threshold(0.6)     // 更严格的边界框阈值
                .with_merge_boxes(true)      // 合并相邻文本框
        )
        .with_rec_options(
            RecOptions::new()
                .with_min_score(0.5)         // 过滤低置信度结果
                .with_batch_size(16)         // 批量识别大小
        );
    
    let engine = OcrEngine::new(det_path, rec_path, charset_path, Some(config))?;
    
    Ok(())
}
```

### 使用特定语言模型

```rust
use ocr_rs::OcrEngine;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 使用韩语模型
    let engine = OcrEngine::new(
        "models/PP-OCRv5_mobile_det.mnn",
        "models/korean_PP-OCRv5_mobile_rec_infer.mnn",
        "models/ppocr_keys_korean.txt",
        None,
    )?;
    
    let image = image::open("korean_text.jpg")?;
    let results = engine.recognize(&image)?;
    
    for result in results {
        println!("{}: {:.2}%", result.text, result.confidence * 100.0);
    }
    
    Ok(())
}
```

### 从内存字节加载模型

适用于嵌入式部署或需要加密模型的场景:

```rust
use ocr_rs::OcrEngine;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 从文件读取模型字节
    let det_bytes = std::fs::read("models/det_model.mnn")?;
    let rec_bytes = std::fs::read("models/rec_model.mnn")?;
    let charset_bytes = std::fs::read("models/ppocr_keys.txt")?;
    
    // 从字节创建引擎
    let engine = OcrEngine::from_bytes(
        &det_bytes,
        &rec_bytes,
        &charset_bytes,
        None,
    )?;
    
    let image = image::open("test.jpg")?;
    let results = engine.recognize(&image)?;
    
    Ok(())
}
```

### 便捷函数

```rust
use ocr_rs::ocr_file;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 一行代码完成 OCR
    let results = ocr_file(
        "test.jpg",
        "models/det_model.mnn",
        "models/rec_model.mnn",
        "models/ppocr_keys.txt",
    )?;
    
    for result in results {
        println!("{}", result.text);
    }
    
    Ok(())
}
```

更多完整示例请参考 [examples](../examples) 目录。

## 相关项目

- 🖥️ **[newbee-ocr-cli](https://github.com/zibo-chen/newbee-ocr-cli)** - 基于本库的命令行工具,提供简单易用的OCR命令行接口
- 🔌 **[paddle-ocr-capi](https://github.com/zibo-chen/paddle-ocr-capi)** - 提供C API绑定,方便其他编程语言(Python、Node.js、Go等)集成
- 🌐 **[newbee-ocr-service](https://github.com/zibo-chen/newbee-ocr-service)** - 基于本库的HTTP服务,提供RESTful API接口 ⚠️ (施工中)

## 性能优化建议

### 1. 选择合适的精度模式

```rust
// 实时处理场景
let config = OcrEngineConfig::fast();
```

### 2. 使用 GPU 加速

```rust
// macOS/iOS
let config = OcrEngineConfig::gpu();  // 使用 Metal

// 其他平台
let config = OcrEngineConfig::new().with_backend(Backend::OpenCL);
```

### 3. 批量处理

```rust
// 批量识别多个文本行,比逐个识别快得多
let results = rec_model.recognize_batch(&images)?;
```


## 贡献

欢迎贡献!请随时提交Issue或Pull Request。



## 许可证

该项目采用Apache许可证2.0版 - 详情请参阅[LICENSE](LICENSE)文件。

## 致谢

- [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) - 提供原始OCR模型和研究
- [MNN](https://github.com/alibaba/MNN) - 提供高效的神经网络推理框架