cnocr 2.3.2.2__tar.gz → 2.3.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. {cnocr-2.3.2.2 → cnocr-2.3.3}/PKG-INFO +32 -15
  2. {cnocr-2.3.2.2 → cnocr-2.3.3}/README.md +30 -13
  3. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/__init__.py +4 -0
  4. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/__version__.py +2 -2
  5. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/cli.py +23 -3
  6. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/cn_ocr.py +31 -5
  7. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/consts.py +16 -0
  8. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/rapid_recognizer.py +106 -6
  9. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/utils.py +62 -12
  10. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/PKG-INFO +32 -15
  11. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/requires.txt +2 -2
  12. {cnocr-2.3.2.2 → cnocr-2.3.3}/setup.py +3 -3
  13. {cnocr-2.3.2.2 → cnocr-2.3.3}/LICENSE +0 -0
  14. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/app.py +0 -0
  15. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/classification/__init__.py +0 -0
  16. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/classification/dataset.py +0 -0
  17. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/classification/image_classifier.py +0 -0
  18. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/clf_cli.py +0 -0
  19. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/consts.py +0 -0
  20. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/data_utils/__init__.py +0 -0
  21. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/data_utils/aug.py +0 -0
  22. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/data_utils/block_shuffle.py +0 -0
  23. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/data_utils/transforms.py +0 -0
  24. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/data_utils/utils.py +0 -0
  25. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/dataset.py +0 -0
  26. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/dataset_utils.py +0 -0
  27. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/gradio_app.py +0 -0
  28. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/gradio_app2.py +0 -0
  29. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/label_cn.txt +0 -0
  30. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/label_number.txt +0 -0
  31. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/line_split.py +0 -0
  32. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/lr_scheduler.py +0 -0
  33. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/models/__init__.py +0 -0
  34. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/models/ctc.py +0 -0
  35. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/models/densenet.py +0 -0
  36. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/models/mobilenet.py +0 -0
  37. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/models/ocr_model.py +0 -0
  38. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/__init__.py +0 -0
  39. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/postprocess/__init__.py +0 -0
  40. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/postprocess/rec_postprocess.py +0 -0
  41. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/pp_recognizer.py +0 -0
  42. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/utility.py +0 -0
  43. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/utils/__init__.py +0 -0
  44. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/utils/chinese_cht_dict.txt +0 -0
  45. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/utils/en_dict.txt +0 -0
  46. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/ppocr/utils/ppocr_keys_v1.txt +0 -0
  47. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/recognizer.py +0 -0
  48. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/serve.py +0 -0
  49. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr/trainer.py +0 -0
  50. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/SOURCES.txt +0 -0
  51. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/dependency_links.txt +0 -0
  52. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/entry_points.txt +0 -0
  53. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/not-zip-safe +0 -0
  54. {cnocr-2.3.2.2 → cnocr-2.3.3}/cnocr.egg-info/top_level.txt +0 -0
  55. {cnocr-2.3.2.2 → cnocr-2.3.3}/setup.cfg +0 -0
  56. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_cnocr.py +0 -0
  57. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_dataset.py +0 -0
  58. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_models.py +0 -0
  59. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_ppocr.py +0 -0
  60. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_pytorch.py +0 -0
  61. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_trainer.py +0 -0
  62. {cnocr-2.3.2.2 → cnocr-2.3.3}/tests/test_transforms.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cnocr
3
- Version: 2.3.2.2
3
+ Version: 2.3.3
4
4
  Summary: Python3 package for Chinese/English OCR, with small pretrained models
5
5
  Home-page: https://github.com/breezedeus/cnocr
6
6
  Author: breezedeus
@@ -16,11 +16,11 @@ Classifier: License :: OSI Approved :: Apache Software License
16
16
  Classifier: Programming Language :: Python
17
17
  Classifier: Programming Language :: Python :: Implementation
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.7
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.8
24
24
  Description-Content-Type: text/markdown
25
25
  Provides-Extra: ort-cpu
26
26
  Provides-Extra: ort-gpu
@@ -69,6 +69,17 @@ License-File: LICENSE
69
69
  ---
70
70
  </div>
71
71
 
72
+ ### Update 2026.07.04:发布 V2.3.3
73
+
74
+ 主要变更:
75
+
76
+ * 基于 RapidOCR 支持 PP-OCRv6 多语种 OCR 模型
77
+ * 新增支持 PP-OCRv6 识别模型:`multi_PP-OCRv6_tiny`、`multi_PP-OCRv6`、`multi_PP-OCRv6_small` 和 `multi_PP-OCRv6_medium`
78
+ * 通过 CnSTD 新增支持 PP-OCRv6 检测模型:`multi_PP-OCRv6_det_tiny`、`multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium`
79
+ * `CnOcr` 新增 `rec_lang_type` 参数,可为 RapidOCR v6 识别模型指定语言类型
80
+ * CLI 新增 `--rec-lang-type` 和 `--det-lang-type`,可为 RapidOCR v6 模型指定语言类型
81
+
82
+
72
83
  ### Update 2025.06.26:发布 V2.3.2
73
84
 
74
85
  主要变更:
@@ -192,13 +203,13 @@ print(out)
192
203
 
193
204
  ### 竖排文字识别
194
205
 
195
- 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的中文识别模型 `rec_model_name='ch_PP-OCRv3'` 进行识别。
206
+ 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的 PP-OCRv6 多语种识别模型 `rec_model_name='multi_PP-OCRv6'` 进行识别。
196
207
 
197
208
  ```python
198
209
  from cnocr import CnOcr
199
210
 
200
211
  img_fp = './docs/examples/shupai.png'
201
- ocr = CnOcr(rec_model_name='ch_PP-OCRv3')
212
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6')
202
213
  out = ocr.ocr(img_fp)
203
214
 
204
215
  print(out)
@@ -233,31 +244,27 @@ print(out)
233
244
 
234
245
  ### 繁体中文识别
235
246
 
236
- 采用来自ppocr的繁体识别模型 `rec_model_name='chinese_cht_PP-OCRv3'` 进行识别。
247
+ 采用来自 ppocr 的 PP-OCRv6 多语种识别模型,并通过 `rec_lang_type='chinese_cht'` 指定繁体中文进行识别。
237
248
 
238
249
  ```python
239
250
  from cnocr import CnOcr
240
251
 
241
252
  img_fp = './docs/examples/fanti.jpg'
242
- ocr = CnOcr(rec_model_name='chinese_cht_PP-OCRv3') # 识别模型使用繁体识别模型
253
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6', rec_lang_type='chinese_cht')
243
254
  out = ocr.ocr(img_fp)
244
255
 
245
256
  print(out)
246
257
  ```
247
258
 
248
- 使用此模型时请注意以下问题:
249
-
250
- * 识别精度一般,不是很好;
251
-
252
- * 除了繁体字,对标点、英文、数字的识别都不好;
253
-
254
- * 此模型不支持竖排文字的识别。
259
+ `multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`chinese_cht` 是繁体中文对应的 `lang_type`。
255
260
 
256
261
  识别结果:
257
262
  <div align="center">
258
263
  <img src="./docs/predict-outputs/fanti.jpg-result.jpg" alt="繁体中文识别" width="700px"/>
259
264
  </div>
260
265
 
266
+ 注:上图中的识别结果来自 V3 模型;V6 模型的识别效果已经有显著增强。
267
+
261
268
 
262
269
  ### 单行文字的图片识别
263
270
 
@@ -331,7 +338,7 @@ $ pip install cnocr[ort-cpu] -i https://mirrors.aliyun.com/pypi/simple
331
338
 
332
339
  > **Note**
333
340
  >
334
- > 请使用 **Python3**(3.7.\*~3.10.\*之间的版本应该都行),没测过Python2下是否ok。
341
+ > 请使用 **Python 3.8 或更高版本**。
335
342
 
336
343
  更多说明可见 [安装文档](https://cnocr.readthedocs.io/zh-cn/stable/install/)。
337
344
 
@@ -428,13 +435,18 @@ print(ocr_out)
428
435
  | db_mobilenet_v3_small | √ | X | cnocr | 7.9 M | 简体中文、繁体中文、英文、数字 | √ |
429
436
  | db_resnet34 | √ | X | cnocr | 86 M | 简体中文、繁体中文、英文、数字 | √ |
430
437
  | db_resnet18 | √ | X | cnocr | 47 M | 简体中文、繁体中文、英文、数字 | √ |
438
+ | multi_PP-OCRv6_det_tiny | X | √ | ppocr | 1.7 M | 多语种(不含日文) | √ |
439
+ | multi_PP-OCRv6_det_small | X | √ | ppocr | 9.5 M | 多语种 | √ |
440
+ | multi_PP-OCRv6_det_medium | X | √ | ppocr | 59 M | 多语种 | √ |
431
441
  | ch_PP-OCRv5_det | X | √ | ppocr | 4.6 M | 简体中文、繁体中文、英文、数字 | √ |
432
- | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
442
+ | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
433
443
  | ch_PP-OCRv4_det | X | √ | ppocr | 4.5 M | 简体中文、繁体中文、英文、数字 | √ |
434
444
  | ch_PP-OCRv4_det_server | X | √ | ppocr | 108 M | 简体中文、繁体中文、英文、数字 | √ |
435
445
  | ch_PP-OCRv3_det | X | √ | ppocr | 2.3 M | 简体中文、繁体中文、英文、数字 | √ |
436
446
  | **en_PP-OCRv3_det** | X | √ | ppocr | 2.3 M | **英文**、数字 | √ |
437
447
 
448
+ PP-OCRv6 的 `multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_det_tiny` 不支持 `japan`。`multi` 是模型族名称,不是可传入的 `lang_type`。
449
+
438
450
 
439
451
 
440
452
  ### 可使用的识别模型
@@ -469,6 +481,9 @@ print(ocr_out)
469
481
  | **number-densenet_lite_136-fc** 🆕 | √ | √ | cnocr | 2.7 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
470
482
  | **number-densenet_lite_136-gru** 🆕 <br /> ([星球会员](https://t.zsxq.com/FEYZRJQ)专享) | √ | √ | cnocr | 5.5 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
471
483
  | **number-densenet_lite_666-gru_large** 🆕 <br />(购买链接:[B站](https://mall.bilibili.com/neul-next/detailuniversal/detail.html?isMerchant=1&page=detailuniversal_detail&saleType=10&itemsId=11884155&loadingShow=1&noTitleBar=1&msource=merchant_share)、[Lemon Squeezy](https://ocr.lemonsqueezy.com/)) | √ | √ | cnocr | 55 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
484
+ | multi_PP-OCRv6_tiny | X | √ | ppocr | 4.3 M | 多语种(不含日文) | √ |
485
+ | multi_PP-OCRv6 / multi_PP-OCRv6_small | X | √ | ppocr | 20 M | 多语种 | √ |
486
+ | multi_PP-OCRv6_medium | X | √ | ppocr | 73 M | 多语种 | √ |
472
487
  | ch_PP-OCRv5 | X | √ | ppocr | 16 M | 简体中文、英文、数字 | √ |
473
488
  | ch_PP-OCRv5_server | X | √ | ppocr | 81 M | 简体中文、英文、数字 | √ |
474
489
  | ch_PP-OCRv4 | X | √ | ppocr | 10 M | 简体中文、英文、数字 | √ |
@@ -484,6 +499,8 @@ print(ocr_out)
484
499
  | latin_PP-OCRv3 | X | √ | ppocr | 8.6 M | **拉丁文**、英文、数字 | √ |
485
500
  | arabic_PP-OCRv3 | X | √ | ppocr | 8.6 M | **阿拉伯文**、英文、数字 | √ |
486
501
 
502
+ PP-OCRv6 的 `multi_PP-OCRv6_small`、`multi_PP-OCRv6_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_tiny` 不支持 `japan`。`multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`multi` 是模型族名称,不是可传入的 `lang_type`。
503
+
487
504
 
488
505
 
489
506
  ## 未来工作
@@ -39,6 +39,17 @@
39
39
  ---
40
40
  </div>
41
41
 
42
+ ### Update 2026.07.04:发布 V2.3.3
43
+
44
+ 主要变更:
45
+
46
+ * 基于 RapidOCR 支持 PP-OCRv6 多语种 OCR 模型
47
+ * 新增支持 PP-OCRv6 识别模型:`multi_PP-OCRv6_tiny`、`multi_PP-OCRv6`、`multi_PP-OCRv6_small` 和 `multi_PP-OCRv6_medium`
48
+ * 通过 CnSTD 新增支持 PP-OCRv6 检测模型:`multi_PP-OCRv6_det_tiny`、`multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium`
49
+ * `CnOcr` 新增 `rec_lang_type` 参数,可为 RapidOCR v6 识别模型指定语言类型
50
+ * CLI 新增 `--rec-lang-type` 和 `--det-lang-type`,可为 RapidOCR v6 模型指定语言类型
51
+
52
+
42
53
  ### Update 2025.06.26:发布 V2.3.2
43
54
 
44
55
  主要变更:
@@ -162,13 +173,13 @@ print(out)
162
173
 
163
174
  ### 竖排文字识别
164
175
 
165
- 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的中文识别模型 `rec_model_name='ch_PP-OCRv3'` 进行识别。
176
+ 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的 PP-OCRv6 多语种识别模型 `rec_model_name='multi_PP-OCRv6'` 进行识别。
166
177
 
167
178
  ```python
168
179
  from cnocr import CnOcr
169
180
 
170
181
  img_fp = './docs/examples/shupai.png'
171
- ocr = CnOcr(rec_model_name='ch_PP-OCRv3')
182
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6')
172
183
  out = ocr.ocr(img_fp)
173
184
 
174
185
  print(out)
@@ -203,31 +214,27 @@ print(out)
203
214
 
204
215
  ### 繁体中文识别
205
216
 
206
- 采用来自ppocr的繁体识别模型 `rec_model_name='chinese_cht_PP-OCRv3'` 进行识别。
217
+ 采用来自 ppocr 的 PP-OCRv6 多语种识别模型,并通过 `rec_lang_type='chinese_cht'` 指定繁体中文进行识别。
207
218
 
208
219
  ```python
209
220
  from cnocr import CnOcr
210
221
 
211
222
  img_fp = './docs/examples/fanti.jpg'
212
- ocr = CnOcr(rec_model_name='chinese_cht_PP-OCRv3') # 识别模型使用繁体识别模型
223
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6', rec_lang_type='chinese_cht')
213
224
  out = ocr.ocr(img_fp)
214
225
 
215
226
  print(out)
216
227
  ```
217
228
 
218
- 使用此模型时请注意以下问题:
219
-
220
- * 识别精度一般,不是很好;
221
-
222
- * 除了繁体字,对标点、英文、数字的识别都不好;
223
-
224
- * 此模型不支持竖排文字的识别。
229
+ `multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`chinese_cht` 是繁体中文对应的 `lang_type`。
225
230
 
226
231
  识别结果:
227
232
  <div align="center">
228
233
  <img src="./docs/predict-outputs/fanti.jpg-result.jpg" alt="繁体中文识别" width="700px"/>
229
234
  </div>
230
235
 
236
+ 注:上图中的识别结果来自 V3 模型;V6 模型的识别效果已经有显著增强。
237
+
231
238
 
232
239
  ### 单行文字的图片识别
233
240
 
@@ -301,7 +308,7 @@ $ pip install cnocr[ort-cpu] -i https://mirrors.aliyun.com/pypi/simple
301
308
 
302
309
  > **Note**
303
310
  >
304
- > 请使用 **Python3**(3.7.\*~3.10.\*之间的版本应该都行),没测过Python2下是否ok。
311
+ > 请使用 **Python 3.8 或更高版本**。
305
312
 
306
313
  更多说明可见 [安装文档](https://cnocr.readthedocs.io/zh-cn/stable/install/)。
307
314
 
@@ -398,13 +405,18 @@ print(ocr_out)
398
405
  | db_mobilenet_v3_small | √ | X | cnocr | 7.9 M | 简体中文、繁体中文、英文、数字 | √ |
399
406
  | db_resnet34 | √ | X | cnocr | 86 M | 简体中文、繁体中文、英文、数字 | √ |
400
407
  | db_resnet18 | √ | X | cnocr | 47 M | 简体中文、繁体中文、英文、数字 | √ |
408
+ | multi_PP-OCRv6_det_tiny | X | √ | ppocr | 1.7 M | 多语种(不含日文) | √ |
409
+ | multi_PP-OCRv6_det_small | X | √ | ppocr | 9.5 M | 多语种 | √ |
410
+ | multi_PP-OCRv6_det_medium | X | √ | ppocr | 59 M | 多语种 | √ |
401
411
  | ch_PP-OCRv5_det | X | √ | ppocr | 4.6 M | 简体中文、繁体中文、英文、数字 | √ |
402
- | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
412
+ | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
403
413
  | ch_PP-OCRv4_det | X | √ | ppocr | 4.5 M | 简体中文、繁体中文、英文、数字 | √ |
404
414
  | ch_PP-OCRv4_det_server | X | √ | ppocr | 108 M | 简体中文、繁体中文、英文、数字 | √ |
405
415
  | ch_PP-OCRv3_det | X | √ | ppocr | 2.3 M | 简体中文、繁体中文、英文、数字 | √ |
406
416
  | **en_PP-OCRv3_det** | X | √ | ppocr | 2.3 M | **英文**、数字 | √ |
407
417
 
418
+ PP-OCRv6 的 `multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_det_tiny` 不支持 `japan`。`multi` 是模型族名称,不是可传入的 `lang_type`。
419
+
408
420
 
409
421
 
410
422
  ### 可使用的识别模型
@@ -439,6 +451,9 @@ print(ocr_out)
439
451
  | **number-densenet_lite_136-fc** 🆕 | √ | √ | cnocr | 2.7 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
440
452
  | **number-densenet_lite_136-gru** 🆕 <br /> ([星球会员](https://t.zsxq.com/FEYZRJQ)专享) | √ | √ | cnocr | 5.5 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
441
453
  | **number-densenet_lite_666-gru_large** 🆕 <br />(购买链接:[B站](https://mall.bilibili.com/neul-next/detailuniversal/detail.html?isMerchant=1&page=detailuniversal_detail&saleType=10&itemsId=11884155&loadingShow=1&noTitleBar=1&msource=merchant_share)、[Lemon Squeezy](https://ocr.lemonsqueezy.com/)) | √ | √ | cnocr | 55 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
454
+ | multi_PP-OCRv6_tiny | X | √ | ppocr | 4.3 M | 多语种(不含日文) | √ |
455
+ | multi_PP-OCRv6 / multi_PP-OCRv6_small | X | √ | ppocr | 20 M | 多语种 | √ |
456
+ | multi_PP-OCRv6_medium | X | √ | ppocr | 73 M | 多语种 | √ |
442
457
  | ch_PP-OCRv5 | X | √ | ppocr | 16 M | 简体中文、英文、数字 | √ |
443
458
  | ch_PP-OCRv5_server | X | √ | ppocr | 81 M | 简体中文、英文、数字 | √ |
444
459
  | ch_PP-OCRv4 | X | √ | ppocr | 10 M | 简体中文、英文、数字 | √ |
@@ -454,6 +469,8 @@ print(ocr_out)
454
469
  | latin_PP-OCRv3 | X | √ | ppocr | 8.6 M | **拉丁文**、英文、数字 | √ |
455
470
  | arabic_PP-OCRv3 | X | √ | ppocr | 8.6 M | **阿拉伯文**、英文、数字 | √ |
456
471
 
472
+ PP-OCRv6 的 `multi_PP-OCRv6_small`、`multi_PP-OCRv6_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_tiny` 不支持 `japan`。`multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`multi` 是模型族名称,不是可传入的 `lang_type`。
473
+
457
474
 
458
475
 
459
476
  ## 未来工作
@@ -17,6 +17,10 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
+ import logging
21
+
22
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
23
+
20
24
  from cnstd.consts import AVAILABLE_MODELS as DET_AVAILABLE_MODELS
21
25
  from cnstd.utils import pil_to_numpy
22
26
 
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # Copyright (C) 2021-2023, [Breezedeus](https://github.com/breezedeus).
2
+ # Copyright (C) 2021-2026, [Breezedeus](https://github.com/breezedeus).
3
3
  # Licensed to the Apache Software Foundation (ASF) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -17,4 +17,4 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- __version__ = '2.3.2.2'
20
+ __version__ = '2.3.3'
@@ -54,6 +54,7 @@ _CONTEXT_SETTINGS = {"help_option_names": ['-h', '--help']}
54
54
  logger = set_logger(log_level=logging.INFO)
55
55
 
56
56
  DEFAULT_MODEL_NAME = 'densenet_lite_136-gru'
57
+ DEFAULT_DET_MODEL_NAME = 'multi_PP-OCRv6_det_small'
57
58
  LEGAL_MODEL_NAMES = {
58
59
  enc_name + '-' + dec_name
59
60
  for enc_name in ENCODER_CONFIGS.keys()
@@ -211,12 +212,18 @@ def visualize_example(example, fp_prefix):
211
212
  default=None,
212
213
  help='识别模型使用的词表。默认取值为 `None` 表示使用系统设定的词表',
213
214
  )
215
+ @click.option(
216
+ '--rec-lang-type',
217
+ type=str,
218
+ default=None,
219
+ help='RapidOCR识别模型的语言类型;PP-OCRv6支持如 ch、en、japan、french、german 等。默认值为 `None`',
220
+ )
214
221
  @click.option(
215
222
  '-d',
216
223
  '--det-model-name',
217
224
  type=str,
218
- default='ch_PP-OCRv5_det',
219
- help='检测模型名称。默认值为 ch_PP-OCRv5_det',
225
+ default=DEFAULT_DET_MODEL_NAME,
226
+ help='检测模型名称。默认值为 %s' % DEFAULT_DET_MODEL_NAME,
220
227
  )
221
228
  @click.option(
222
229
  '--det-model-backend',
@@ -224,6 +231,12 @@ def visualize_example(example, fp_prefix):
224
231
  default='onnx',
225
232
  help='检测模型类型。默认值为 `onnx`',
226
233
  )
234
+ @click.option(
235
+ '--det-lang-type',
236
+ type=str,
237
+ default=None,
238
+ help='RapidOCR检测模型的语言类型;PP-OCRv6支持如 ch、en、japan、french、german 等。默认值为 `None`',
239
+ )
227
240
  @click.option(
228
241
  '--det-resized-shape', type=int, default=768, help='检测模型输入图像尺寸。默认值为 768',
229
242
  )
@@ -264,8 +277,10 @@ def predict(
264
277
  rec_model_name,
265
278
  rec_model_backend,
266
279
  rec_vocab_fp,
280
+ rec_lang_type,
267
281
  det_model_name,
268
282
  det_model_backend,
283
+ det_lang_type,
269
284
  det_resized_shape,
270
285
  pretrained_model_fp,
271
286
  context,
@@ -295,6 +310,10 @@ def predict(
295
310
  if len(fp_list) == 0:
296
311
  raise ValueError(f'No image is found from "{img_file_or_dir}".')
297
312
 
313
+ det_more_configs = {}
314
+ if det_lang_type is not None:
315
+ det_more_configs['lang_type'] = det_lang_type
316
+
298
317
  ocr = CnOcr(
299
318
  rec_model_name=rec_model_name,
300
319
  rec_model_backend=rec_model_backend,
@@ -302,8 +321,9 @@ def predict(
302
321
  det_model_name=det_model_name,
303
322
  det_model_backend=det_model_backend,
304
323
  rec_model_fp=pretrained_model_fp,
324
+ rec_lang_type=rec_lang_type,
325
+ det_more_configs=det_more_configs,
305
326
  context=context,
306
- # det_more_configs={'rotated_bbox': False},
307
327
  )
308
328
  ocr_func = ocr.ocr_for_single_line if single_line else ocr.ocr
309
329
  ocr_kwargs = {}
@@ -27,12 +27,16 @@ from pathlib import Path
27
27
  import numpy as np
28
28
  import torch
29
29
  from PIL import Image
30
+ from rapidocr import LangRec
30
31
  from cnstd.consts import AVAILABLE_MODELS as DET_AVAILABLE_MODELS
31
32
  from cnstd import CnStd
32
33
  from cnstd.utils import data_dir as det_data_dir
33
34
 
34
35
  from .consts import AVAILABLE_MODELS as REC_AVAILABLE_MODELS
35
- from .utils import data_dir, read_img
36
+ from .utils import (
37
+ data_dir,
38
+ read_img,
39
+ )
36
40
  from .line_split import line_split
37
41
  from .recognizer import Recognizer
38
42
  from .ppocr import PPRecognizer, RapidRecognizer, PP_SPACE
@@ -64,12 +68,13 @@ class CnOcr(object):
64
68
  self,
65
69
  rec_model_name: str = 'densenet_lite_136-gru',
66
70
  *,
67
- det_model_name: str = 'ch_PP-OCRv5_det',
71
+ det_model_name: str = 'multi_PP-OCRv6_det_small',
68
72
  cand_alphabet: Optional[Union[Collection, str]] = None,
69
73
  context: str = 'cpu', # ['cpu', 'gpu', 'cuda']
70
74
  rec_model_fp: Optional[str] = None,
71
75
  rec_model_backend: str = 'onnx', # ['pytorch', 'onnx']
72
76
  rec_vocab_fp: Optional[Union[str, Path]] = None,
77
+ rec_lang_type: Optional[Union[str, LangRec]] = None,
73
78
  rec_more_configs: Optional[Dict[str, Any]] = None,
74
79
  rec_root: Union[str, Path] = data_dir(),
75
80
  det_model_fp: Optional[str] = None,
@@ -83,7 +88,7 @@ class CnOcr(object):
83
88
 
84
89
  Args:
85
90
  rec_model_name (str): 识别模型名称。默认为 `densenet_lite_136-gru`
86
- det_model_name (str): 检测模型名称。默认为 `ch_PP-OCRv5_det`
91
+ det_model_name (str): 检测模型名称。默认为 `multi_PP-OCRv6_det_small`
87
92
  cand_alphabet (Optional[Union[Collection, str]]): 待识别字符所在的候选集合。默认为 `None`,表示不限定识别字符范围
88
93
  context (str): 'cpu', or 'gpu'。表明预测时是使用CPU还是GPU。默认为 `cpu`。
89
94
  此参数仅在 `model_backend=='pytorch'` 时有效。
@@ -92,6 +97,8 @@ class CnOcr(object):
92
97
  同样的模型,ONNX 版本的预测速度一般是 PyTorch 版本的2倍左右。默认为 'onnx'。
93
98
  rec_vocab_fp (Optional[Union[str, Path]]): 识别字符集合的文件路径,即 `label_cn.txt` 文件路径。取值为 `None` 表示使用系统设定的词表。
94
99
  若训练的自有模型更改了字符集,看通过此参数传入新的字符集文件路径。
100
+ rec_lang_type (Optional[Union[str, LangRec]]): RapidOCR识别模型语言类型。PP-OCRv6
101
+ 需传入具体语言,如 `ch`、`en`、`japan`、`french` 等;默认为中文。
95
102
  rec_more_configs (Optional[Dict[str, Any]]): 识别模型初始化时传入的其他参数。
96
103
  rec_root (Union[str, Path]): 识别模型文件所在的根目录。
97
104
  Linux/Mac下默认值为 `~/.cnocr`,表示模型文件所处文件夹类似 `~/.cnocr/2.3/densenet_lite_136-gru`。
@@ -101,7 +108,7 @@ class CnOcr(object):
101
108
  同样的模型,ONNX 版本的预测速度一般是 PyTorch 版本的2倍左右。默认为 'onnx'。
102
109
  det_more_configs (Optional[Dict[str, Any]]): 识别模型初始化时传入的其他参数。
103
110
  det_root: 检测模型文件所在的根目录。
104
- Linux/Mac下默认值为 `~/.cnstd`,表示模型文件所处文件夹类似 `~/.cnstd/1.2/db_resnet18`
111
+ Linux/Mac下默认值为 `~/.cnstd`,表示模型文件所处文件夹类似 `~/.cnstd/1.2/ppocr/multi_PP-OCRv6_det_small`
105
112
  Windows下默认值为 `C:/Users/<username>/AppData/Roaming/cnstd`。
106
113
  **kwargs: 目前未被使用。
107
114
 
@@ -152,7 +159,14 @@ class CnOcr(object):
152
159
  '%s is not supported currently' % ((rec_model_name, rec_model_backend),)
153
160
  )
154
161
 
155
- rec_more_configs = rec_more_configs or dict()
162
+ rec_more_configs = dict(rec_more_configs or {})
163
+ if rec_lang_type is not None:
164
+ if 'lang_type' in rec_more_configs:
165
+ logger.warning(
166
+ 'both `rec_lang_type` and `rec_more_configs["lang_type"]` are set; '
167
+ '`rec_lang_type` will be used'
168
+ )
169
+ rec_more_configs['lang_type'] = rec_lang_type
156
170
  self.rec_model = rec_cls(
157
171
  model_name=rec_model_name,
158
172
  model_backend=rec_model_backend,
@@ -163,6 +177,18 @@ class CnOcr(object):
163
177
  vocab_fp=rec_vocab_fp,
164
178
  **rec_more_configs,
165
179
  )
180
+ rec_effective_lang_type = getattr(self.rec_model, '_lang_type', None)
181
+ rec_effective_lang_type = getattr(
182
+ rec_effective_lang_type, 'value', rec_effective_lang_type
183
+ )
184
+ logger.info(
185
+ 'use rec model: name=%s, backend=%s, lang_type=%s, fp=%s',
186
+ rec_model_name,
187
+ rec_model_backend,
188
+ rec_effective_lang_type,
189
+ getattr(self.rec_model, '_model_fp', rec_model_fp),
190
+ extra={'log_color': 'green'},
191
+ )
166
192
 
167
193
  self.det_model = None
168
194
  if det_model_name in DET_MODLE_NAMES:
@@ -81,6 +81,22 @@ MODEL_LABELS_FILE_DICT = {
81
81
  "recognizer": "RapidRecognizer",
82
82
  "repo": "breezedeus/cnocr-ppocr-ch_PP-OCRv5_server",
83
83
  },
84
+ ("multi_PP-OCRv6_tiny", "onnx"): {
85
+ "recognizer": "RapidRecognizer",
86
+ "repo": "breezedeus/cnocr-ppocr-multi_PP-OCRv6_tiny",
87
+ },
88
+ ("multi_PP-OCRv6", "onnx"): {
89
+ "recognizer": "RapidRecognizer",
90
+ "repo": "breezedeus/cnocr-ppocr-multi_PP-OCRv6",
91
+ },
92
+ ("multi_PP-OCRv6_small", "onnx"): {
93
+ "recognizer": "RapidRecognizer",
94
+ "repo": "breezedeus/cnocr-ppocr-multi_PP-OCRv6_small",
95
+ },
96
+ ("multi_PP-OCRv6_medium", "onnx"): {
97
+ "recognizer": "RapidRecognizer",
98
+ "repo": "breezedeus/cnocr-ppocr-multi_PP-OCRv6_medium",
99
+ },
84
100
  }
85
101
 
86
102
  PP_SPACE = "ppocr"
@@ -7,10 +7,12 @@ import os
7
7
  import logging
8
8
  from typing import Union, Optional, List, Tuple
9
9
  from pathlib import Path
10
+ from copy import deepcopy
10
11
 
11
12
  import numpy as np
12
13
  from rapidocr import EngineType, LangRec, ModelType, OCRVersion
13
14
  from rapidocr.utils.typings import TaskType
15
+ from rapidocr.utils.model_resolver import resolve_model_key
14
16
  from rapidocr.ch_ppocr_rec import TextRecognizer, TextRecInput
15
17
  from cnstd.utils import prepare_model_files
16
18
 
@@ -32,6 +34,8 @@ class Config(dict):
32
34
  "task_type": TaskType.REC,
33
35
  "model_path": None,
34
36
  "model_dir": None,
37
+ "model_root_dir": None,
38
+ "font_path": None,
35
39
  "rec_keys_path": None,
36
40
  "rec_img_shape": [3, 48, 320],
37
41
  "rec_batch_num": 6,
@@ -88,6 +92,7 @@ class RapidRecognizer(Recognizer):
88
92
  root: Union[str, Path] = data_dir(),
89
93
  context: str = "cpu", # ['cpu', 'gpu']
90
94
  rec_image_shape: str = "3, 48, 320",
95
+ lang_type: Optional[Union[str, LangRec]] = None,
91
96
  **kwargs
92
97
  ):
93
98
  """
@@ -99,16 +104,24 @@ class RapidRecognizer(Recognizer):
99
104
  root (Union[str, Path]): 模型文件所在的根目录
100
105
  context (str): 使用的设备。默认为 `cpu`,可选 `gpu`
101
106
  rec_image_shape (str): 输入图片尺寸,无需更改使用默认值即可。默认值:`"3, 48, 320"`
107
+ lang_type (Optional[Union[str, LangRec]]): RapidOCR识别模型语言类型。PP-OCRv6
108
+ 需传入具体语言,如 `ch`、`en`、`japan`、`french` 等;默认为中文。
102
109
  **kwargs: 其他参数
103
110
  """
104
111
  self.rec_image_shape = [int(v) for v in rec_image_shape.split(",")]
105
112
  self._model_name = model_name
106
113
  self._model_backend = "onnx"
107
114
  use_gpu = context.lower() not in ("cpu", "mps")
115
+ model_type = self._get_model_type(model_name)
116
+ ocr_version = self._get_ocr_version(model_name)
117
+ lang_type = self._get_lang_type(model_name, model_type, lang_type)
118
+ self._model_type = model_type
119
+ self._ocr_version = ocr_version
120
+ self._lang_type = lang_type
108
121
 
109
122
  self._assert_and_prepare_model_files(model_fp, root)
110
123
 
111
- config = Config.DEFAULT_CFG
124
+ config = deepcopy(Config.DEFAULT_CFG)
112
125
  ## add custom font path
113
126
  if 'font_path' in kwargs:
114
127
  config['font_path'] = kwargs['font_path']
@@ -117,24 +130,111 @@ class RapidRecognizer(Recognizer):
117
130
  config["engine_cfg"].update(kwargs["engine_cfg"])
118
131
  config["rec_img_shape"] = self.rec_image_shape
119
132
  config["model_path"] = self._model_fp
133
+ config["model_root_dir"] = self._model_dir
120
134
  # 从 model_name 中获取 model_type 和 ocr_version
121
- config["model_type"] = ModelType.SERVER if "server" in model_name else ModelType.MOBILE
122
- config["ocr_version"] = OCRVersion.PPOCRV5 if "v5" in model_name else OCRVersion.PPOCRV4
135
+ config["model_type"] = model_type
136
+ config["ocr_version"] = ocr_version
137
+ config["lang_type"] = lang_type
123
138
 
124
139
  config = Config(config)
125
140
  self.recognizer = TextRecognizer(config)
126
141
 
142
+ @staticmethod
143
+ def _get_ocr_version(model_name: str):
144
+ if "v6" in model_name:
145
+ if not hasattr(OCRVersion, "PPOCRV6"):
146
+ raise RuntimeError(
147
+ "PP-OCRv6 models require rapidocr>=3.9.0. "
148
+ "Please upgrade rapidocr to use this model."
149
+ )
150
+ return OCRVersion.PPOCRV6
151
+ if "v5" in model_name:
152
+ return OCRVersion.PPOCRV5
153
+ return OCRVersion.PPOCRV4
154
+
155
+ @staticmethod
156
+ def _get_model_type(model_name: str):
157
+ if "server" in model_name:
158
+ return ModelType.SERVER
159
+ for model_type in ("tiny", "small", "medium"):
160
+ if model_type in model_name:
161
+ if not hasattr(ModelType, model_type.upper()):
162
+ raise RuntimeError(
163
+ "PP-OCRv6 models require rapidocr>=3.9.0. "
164
+ "Please upgrade rapidocr to use this model."
165
+ )
166
+ return getattr(ModelType, model_type.upper())
167
+ if "v6" in model_name:
168
+ if not hasattr(ModelType, "SMALL"):
169
+ raise RuntimeError(
170
+ "PP-OCRv6 models require rapidocr>=3.9.0. "
171
+ "Please upgrade rapidocr to use this model."
172
+ )
173
+ return ModelType.SMALL
174
+ return ModelType.MOBILE
175
+
176
+ @classmethod
177
+ def _get_model_file_name(cls, model_name: str):
178
+ if "v6" in model_name:
179
+ model_type = cls._get_model_type(model_name).value
180
+ return f"PP-OCRv6_rec_{model_type}.onnx"
181
+ return "%s_rec_infer.onnx" % model_name
182
+
183
+ @staticmethod
184
+ def _get_lang_type(model_name: str, model_type: ModelType, lang_type=None):
185
+ # RapidOCR's PP-OCRv6 model files are named "multi_*", but its
186
+ # resolver expects a concrete language and maps it to the multi model.
187
+ if lang_type is None:
188
+ return LangRec.CH
189
+
190
+ normalized = lang_type.value if hasattr(lang_type, "value") else str(lang_type)
191
+ normalized = normalized.strip().lower()
192
+ if "v6" in model_name and normalized == "multi":
193
+ raise ValueError(
194
+ "PP-OCRv6 requires a concrete lang_type such as 'ch' or 'en'; "
195
+ "'multi' is the model family name, not a valid v6 lang_type."
196
+ )
197
+ if "v6" in model_name:
198
+ resolve_model_key(
199
+ TaskType.REC, OCRVersion.PPOCRV6, lang_type, model_type
200
+ )
201
+ return lang_type
202
+
127
203
  def _assert_and_prepare_model_files(self, model_fp, root):
128
204
  if model_fp is not None and not os.path.isfile(model_fp):
129
205
  raise FileNotFoundError("can not find model file %s" % model_fp)
130
206
 
207
+ root = os.path.join(root, MODEL_VERSION)
208
+ self._model_dir = os.path.join(root, PP_SPACE, self._model_name)
209
+
131
210
  if model_fp is not None:
132
211
  self._model_fp = model_fp
133
212
  return
134
213
 
135
- root = os.path.join(root, MODEL_VERSION)
136
- self._model_dir = os.path.join(root, PP_SPACE, self._model_name)
137
- model_fp = os.path.join(self._model_dir, "%s_rec_infer.onnx" % self._model_name)
214
+ if "v6" in self._model_name:
215
+ if (self._model_name, self._model_backend) not in AVAILABLE_MODELS:
216
+ raise NotImplementedError(
217
+ "%s is not a downloadable model"
218
+ % ((self._model_name, self._model_backend),)
219
+ )
220
+ remote_repo = AVAILABLE_MODELS.get_value(
221
+ self._model_name, self._model_backend, "repo"
222
+ )
223
+ if remote_repo is None:
224
+ raise RuntimeError(
225
+ "no remote repo is configured for model %s"
226
+ % ((self._model_name, self._model_backend),)
227
+ )
228
+ model_fp = os.path.join(
229
+ self._model_dir, self._get_model_file_name(self._model_name)
230
+ )
231
+ self._model_fp = str(prepare_model_files(model_fp, remote_repo))
232
+ logger.info("use model: %s" % self._model_fp)
233
+ return
234
+
235
+ model_fp = os.path.join(
236
+ self._model_dir, self._get_model_file_name(self._model_name)
237
+ )
138
238
  if not os.path.isfile(model_fp):
139
239
  logger.warning("can not find model file %s" % model_fp)
140
240
  if (self._model_name, self._model_backend) not in AVAILABLE_MODELS:
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
- # Copyright (C) 2021-2023, [Breezedeus](https://github.com/breezedeus).
2
+ # Copyright (C) 2021-2026, [Breezedeus](https://github.com/breezedeus).
3
3
  # Licensed to the Apache Software Foundation (ASF) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -39,14 +39,54 @@ import torchvision.transforms.functional as F
39
39
  from .consts import (
40
40
  ENCODER_CONFIGS,
41
41
  DECODER_CONFIGS,
42
- AVAILABLE_MODELS,
43
42
  IMG_STANDARD_HEIGHT,
44
43
  )
45
44
 
46
- fmt = '[%(levelname)s %(asctime)s %(funcName)s:%(lineno)d] %(' 'message)s '
47
- logging.basicConfig(format=fmt)
48
- logging.captureWarnings(True)
49
- logger = logging.getLogger()
45
+ LOG_FMT = '[%(levelname)s] %(asctime)s [%(package_name)s] %(filename)s:%(lineno)d: %(message)s'
46
+ GREEN = '\033[32m'
47
+ RESET = '\033[0m'
48
+
49
+
50
+ def _package_label(logger_name):
51
+ if logger_name.startswith('cnocr'):
52
+ return 'CnOCR'
53
+ if logger_name.startswith('cnstd'):
54
+ return 'CnSTD'
55
+ if logger_name.startswith('RapidOCR'):
56
+ return 'RapidOCR'
57
+ return logger_name.split('.', maxsplit=1)[0]
58
+
59
+
60
+ class PackageFormatter(logging.Formatter):
61
+ def format(self, record):
62
+ record.package_name = _package_label(record.name)
63
+ return super().format(record)
64
+
65
+
66
+ class ColoredFormatter(PackageFormatter):
67
+ def format(self, record):
68
+ msg = super().format(record)
69
+ if getattr(record, 'log_color', None) == 'green':
70
+ return GREEN + msg + RESET
71
+ return msg
72
+
73
+ logger = logging.getLogger(__name__)
74
+
75
+
76
+ def set_rapidocr_logger_level(log_level=logging.WARNING):
77
+ logging.getLogger('RapidOCR').setLevel(log_level)
78
+
79
+
80
+ def _console_handler():
81
+ console_handler = logging.StreamHandler()
82
+ console_handler.setFormatter(ColoredFormatter(LOG_FMT))
83
+ return console_handler
84
+
85
+
86
+ def get_logger(name=__name__, log_level=logging.INFO):
87
+ logger = logging.getLogger(name)
88
+ logger.setLevel(log_level)
89
+ return logger
50
90
 
51
91
 
52
92
  def set_logger(log_file=None, log_level=logging.INFO, log_file_level=logging.NOTSET):
@@ -55,11 +95,19 @@ def set_logger(log_file=None, log_level=logging.INFO, log_file_level=logging.NOT
55
95
  >>> set_logger(log_file)
56
96
  >>> logger.info("abc'")
57
97
  """
58
- log_format = logging.Formatter(fmt)
59
- logger.setLevel(log_level)
60
- console_handler = logging.StreamHandler()
61
- console_handler.setFormatter(log_format)
62
- logger.handlers = [console_handler]
98
+ global logger
99
+ log_format = PackageFormatter(LOG_FMT)
100
+ logging.captureWarnings(True)
101
+ set_rapidocr_logger_level()
102
+
103
+ root_logger = logging.getLogger()
104
+ root_logger.setLevel(log_level)
105
+ root_logger.handlers = [_console_handler()]
106
+ for package_name in ('cnocr', 'cnstd'):
107
+ package_logger = logging.getLogger(package_name)
108
+ package_logger.setLevel(logging.NOTSET)
109
+ package_logger.propagate = True
110
+
63
111
  if log_file and log_file != '':
64
112
  if not Path(log_file).parent.exists():
65
113
  os.makedirs(Path(log_file).parent)
@@ -68,7 +116,9 @@ def set_logger(log_file=None, log_level=logging.INFO, log_file_level=logging.NOT
68
116
  file_handler = logging.FileHandler(log_file)
69
117
  file_handler.setLevel(log_file_level)
70
118
  file_handler.setFormatter(log_format)
71
- logger.addHandler(file_handler)
119
+ root_logger.addHandler(file_handler)
120
+ logger = logging.getLogger(__name__)
121
+ logger.setLevel(log_level)
72
122
  return logger
73
123
 
74
124
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cnocr
3
- Version: 2.3.2.2
3
+ Version: 2.3.3
4
4
  Summary: Python3 package for Chinese/English OCR, with small pretrained models
5
5
  Home-page: https://github.com/breezedeus/cnocr
6
6
  Author: breezedeus
@@ -16,11 +16,11 @@ Classifier: License :: OSI Approved :: Apache Software License
16
16
  Classifier: Programming Language :: Python
17
17
  Classifier: Programming Language :: Python :: Implementation
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.7
20
19
  Classifier: Programming Language :: Python :: 3.8
21
20
  Classifier: Programming Language :: Python :: 3.9
22
21
  Classifier: Programming Language :: Python :: 3.10
23
22
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
23
+ Requires-Python: >=3.8
24
24
  Description-Content-Type: text/markdown
25
25
  Provides-Extra: ort-cpu
26
26
  Provides-Extra: ort-gpu
@@ -69,6 +69,17 @@ License-File: LICENSE
69
69
  ---
70
70
  </div>
71
71
 
72
+ ### Update 2026.07.04:发布 V2.3.3
73
+
74
+ 主要变更:
75
+
76
+ * 基于 RapidOCR 支持 PP-OCRv6 多语种 OCR 模型
77
+ * 新增支持 PP-OCRv6 识别模型:`multi_PP-OCRv6_tiny`、`multi_PP-OCRv6`、`multi_PP-OCRv6_small` 和 `multi_PP-OCRv6_medium`
78
+ * 通过 CnSTD 新增支持 PP-OCRv6 检测模型:`multi_PP-OCRv6_det_tiny`、`multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium`
79
+ * `CnOcr` 新增 `rec_lang_type` 参数,可为 RapidOCR v6 识别模型指定语言类型
80
+ * CLI 新增 `--rec-lang-type` 和 `--det-lang-type`,可为 RapidOCR v6 模型指定语言类型
81
+
82
+
72
83
  ### Update 2025.06.26:发布 V2.3.2
73
84
 
74
85
  主要变更:
@@ -192,13 +203,13 @@ print(out)
192
203
 
193
204
  ### 竖排文字识别
194
205
 
195
- 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的中文识别模型 `rec_model_name='ch_PP-OCRv3'` 进行识别。
206
+ 采用来自 [**PaddleOCR**](https://github.com/PaddlePaddle/PaddleOCR)(之后简称 **ppocr**)的 PP-OCRv6 多语种识别模型 `rec_model_name='multi_PP-OCRv6'` 进行识别。
196
207
 
197
208
  ```python
198
209
  from cnocr import CnOcr
199
210
 
200
211
  img_fp = './docs/examples/shupai.png'
201
- ocr = CnOcr(rec_model_name='ch_PP-OCRv3')
212
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6')
202
213
  out = ocr.ocr(img_fp)
203
214
 
204
215
  print(out)
@@ -233,31 +244,27 @@ print(out)
233
244
 
234
245
  ### 繁体中文识别
235
246
 
236
- 采用来自ppocr的繁体识别模型 `rec_model_name='chinese_cht_PP-OCRv3'` 进行识别。
247
+ 采用来自 ppocr 的 PP-OCRv6 多语种识别模型,并通过 `rec_lang_type='chinese_cht'` 指定繁体中文进行识别。
237
248
 
238
249
  ```python
239
250
  from cnocr import CnOcr
240
251
 
241
252
  img_fp = './docs/examples/fanti.jpg'
242
- ocr = CnOcr(rec_model_name='chinese_cht_PP-OCRv3') # 识别模型使用繁体识别模型
253
+ ocr = CnOcr(rec_model_name='multi_PP-OCRv6', rec_lang_type='chinese_cht')
243
254
  out = ocr.ocr(img_fp)
244
255
 
245
256
  print(out)
246
257
  ```
247
258
 
248
- 使用此模型时请注意以下问题:
249
-
250
- * 识别精度一般,不是很好;
251
-
252
- * 除了繁体字,对标点、英文、数字的识别都不好;
253
-
254
- * 此模型不支持竖排文字的识别。
259
+ `multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`chinese_cht` 是繁体中文对应的 `lang_type`。
255
260
 
256
261
  识别结果:
257
262
  <div align="center">
258
263
  <img src="./docs/predict-outputs/fanti.jpg-result.jpg" alt="繁体中文识别" width="700px"/>
259
264
  </div>
260
265
 
266
+ 注:上图中的识别结果来自 V3 模型;V6 模型的识别效果已经有显著增强。
267
+
261
268
 
262
269
  ### 单行文字的图片识别
263
270
 
@@ -331,7 +338,7 @@ $ pip install cnocr[ort-cpu] -i https://mirrors.aliyun.com/pypi/simple
331
338
 
332
339
  > **Note**
333
340
  >
334
- > 请使用 **Python3**(3.7.\*~3.10.\*之间的版本应该都行),没测过Python2下是否ok。
341
+ > 请使用 **Python 3.8 或更高版本**。
335
342
 
336
343
  更多说明可见 [安装文档](https://cnocr.readthedocs.io/zh-cn/stable/install/)。
337
344
 
@@ -428,13 +435,18 @@ print(ocr_out)
428
435
  | db_mobilenet_v3_small | √ | X | cnocr | 7.9 M | 简体中文、繁体中文、英文、数字 | √ |
429
436
  | db_resnet34 | √ | X | cnocr | 86 M | 简体中文、繁体中文、英文、数字 | √ |
430
437
  | db_resnet18 | √ | X | cnocr | 47 M | 简体中文、繁体中文、英文、数字 | √ |
438
+ | multi_PP-OCRv6_det_tiny | X | √ | ppocr | 1.7 M | 多语种(不含日文) | √ |
439
+ | multi_PP-OCRv6_det_small | X | √ | ppocr | 9.5 M | 多语种 | √ |
440
+ | multi_PP-OCRv6_det_medium | X | √ | ppocr | 59 M | 多语种 | √ |
431
441
  | ch_PP-OCRv5_det | X | √ | ppocr | 4.6 M | 简体中文、繁体中文、英文、数字 | √ |
432
- | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
442
+ | ch_PP-OCRv5_det_server | X | √ | ppocr | 84 M | 简体中文、繁体中文、英文、数字 | √ |
433
443
  | ch_PP-OCRv4_det | X | √ | ppocr | 4.5 M | 简体中文、繁体中文、英文、数字 | √ |
434
444
  | ch_PP-OCRv4_det_server | X | √ | ppocr | 108 M | 简体中文、繁体中文、英文、数字 | √ |
435
445
  | ch_PP-OCRv3_det | X | √ | ppocr | 2.3 M | 简体中文、繁体中文、英文、数字 | √ |
436
446
  | **en_PP-OCRv3_det** | X | √ | ppocr | 2.3 M | **英文**、数字 | √ |
437
447
 
448
+ PP-OCRv6 的 `multi_PP-OCRv6_det_small` 和 `multi_PP-OCRv6_det_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_det_tiny` 不支持 `japan`。`multi` 是模型族名称,不是可传入的 `lang_type`。
449
+
438
450
 
439
451
 
440
452
  ### 可使用的识别模型
@@ -469,6 +481,9 @@ print(ocr_out)
469
481
  | **number-densenet_lite_136-fc** 🆕 | √ | √ | cnocr | 2.7 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
470
482
  | **number-densenet_lite_136-gru** 🆕 <br /> ([星球会员](https://t.zsxq.com/FEYZRJQ)专享) | √ | √ | cnocr | 5.5 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
471
483
  | **number-densenet_lite_666-gru_large** 🆕 <br />(购买链接:[B站](https://mall.bilibili.com/neul-next/detailuniversal/detail.html?isMerchant=1&page=detailuniversal_detail&saleType=10&itemsId=11884155&loadingShow=1&noTitleBar=1&msource=merchant_share)、[Lemon Squeezy](https://ocr.lemonsqueezy.com/)) | √ | √ | cnocr | 55 M | **纯数字**(仅包含 `0~9` 十个数字) | X |
484
+ | multi_PP-OCRv6_tiny | X | √ | ppocr | 4.3 M | 多语种(不含日文) | √ |
485
+ | multi_PP-OCRv6 / multi_PP-OCRv6_small | X | √ | ppocr | 20 M | 多语种 | √ |
486
+ | multi_PP-OCRv6_medium | X | √ | ppocr | 73 M | 多语种 | √ |
472
487
  | ch_PP-OCRv5 | X | √ | ppocr | 16 M | 简体中文、英文、数字 | √ |
473
488
  | ch_PP-OCRv5_server | X | √ | ppocr | 81 M | 简体中文、英文、数字 | √ |
474
489
  | ch_PP-OCRv4 | X | √ | ppocr | 10 M | 简体中文、英文、数字 | √ |
@@ -484,6 +499,8 @@ print(ocr_out)
484
499
  | latin_PP-OCRv3 | X | √ | ppocr | 8.6 M | **拉丁文**、英文、数字 | √ |
485
500
  | arabic_PP-OCRv3 | X | √ | ppocr | 8.6 M | **阿拉伯文**、英文、数字 | √ |
486
501
 
502
+ PP-OCRv6 的 `multi_PP-OCRv6_small`、`multi_PP-OCRv6_medium` 支持的 `lang_type` 包括:`ch`, `chinese_cht`, `en`, `japan`, `af`, `az`, `bs`, `ca`, `cs`, `cy`, `da`, `de`, `es`, `et`, `eu`, `fi`, `fr`, `ga`, `gl`, `hr`, `hu`, `id`, `is`, `it`, `ku`, `la`, `lb`, `lt`, `lv`, `mi`, `ms`, `mt`, `nl`, `no`, `oc`, `pl`, `pt`, `qu`, `rm`, `ro`, `rs_latin`, `sk`, `sl`, `sq`, `sv`, `sw`, `tl`, `tr`, `uz`, `vi`, `french`, `german`;`multi_PP-OCRv6_tiny` 不支持 `japan`。`multi_PP-OCRv6` 是 `multi_PP-OCRv6_small` 的别名;`multi` 是模型族名称,不是可传入的 `lang_type`。
503
+
487
504
 
488
505
 
489
506
  ## 未来工作
@@ -8,8 +8,8 @@ wandb
8
8
  torchmetrics
9
9
  pillow>=5.3.0
10
10
  onnx
11
- cnstd>=1.2.6
12
- rapidocr>=3.0
11
+ cnstd>=1.2.8
12
+ rapidocr>=3.9.1
13
13
 
14
14
  [dev]
15
15
  albumentations
@@ -47,8 +47,8 @@ required = [
47
47
  "torchmetrics",
48
48
  "pillow>=5.3.0",
49
49
  "onnx",
50
- "cnstd>=1.2.6",
51
- "rapidocr>=3.0",
50
+ "cnstd>=1.2.8",
51
+ "rapidocr>=3.9.1",
52
52
  ]
53
53
  extras_require = {
54
54
  "ort-cpu": ["onnxruntime"],
@@ -91,6 +91,7 @@ setup(
91
91
  entry_points=entry_points,
92
92
  install_requires=required,
93
93
  extras_require=extras_require,
94
+ python_requires='>=3.8',
94
95
  zip_safe=False,
95
96
  classifiers=[
96
97
  'Development Status :: 4 - Beta',
@@ -100,7 +101,6 @@ setup(
100
101
  'Programming Language :: Python',
101
102
  'Programming Language :: Python :: Implementation',
102
103
  'Programming Language :: Python :: 3',
103
- 'Programming Language :: Python :: 3.7',
104
104
  'Programming Language :: Python :: 3.8',
105
105
  'Programming Language :: Python :: 3.9',
106
106
  'Programming Language :: Python :: 3.10',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes