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
# 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 설계**: 저수준 모델부터 고수준 파이프라인까지 완전한 계층형 API 제공
- 🔧 **유연한 모델 로딩**: 파일 경로 또는 메모리 바이트에서 모델 로딩 지원
- ⚙️ **설정 가능한 검출 매개변수**: 검출 임계값, 해상도, 정밀도 모드 등 사용자 정의 지원
- 🚀 **GPU 가속 지원**: Metal, OpenCL, Vulkan 등 다양한 GPU 백엔드 지원
- 📦 **배치 처리 최적화**: 처리량을 높이기 위한 텍스트 인식 배치 처리 지원
- 🔌 **독립 엔진 모드**: 검출 엔진 또는 인식 엔진만 별도로 생성 가능

## 특징

### 핵심 기능
- **텍스트 검출**: 이미지 내 텍스트 영역을 정확하게 포착
- **텍스트 인식**: 검출된 영역의 텍스트 내용을 인식
- **엔드투엔드(End-to-End) 인식**: 한 번의 호출로 검출 및 인식 전체 프로세스 완료
- **계층형 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을 빌드하는 방식으로 폴백합니다.

#### 소스에서 강제 빌드

사용자 정의 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. 검출 모델을 가져와 수동으로 크롭(Crop)
    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 CLI 인터페이스를 제공합니다.
- 🔌 **[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 License, Version 2.0에 따라 라이선스가 부여됩니다. 자세한 내용은 [LICENSE](LICENSE) 파일을 참조하세요.

## 감사의 말

- [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR) - 원본 OCR 모델 및 연구 제공
- [MNN](https://github.com/alibaba/MNN) - 고효율 신경망 추론 프레임워크 제공