openocr-mlt-cuda 0.4.0__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.
- openocr_mlt_cuda-0.4.0/MANIFEST.in +7 -0
- openocr_mlt_cuda-0.4.0/PKG-INFO +120 -0
- openocr_mlt_cuda-0.4.0/README.md +94 -0
- openocr_mlt_cuda-0.4.0/THIRD_PARTY_NOTICES.md +26 -0
- openocr_mlt_cuda-0.4.0/docs/INSTALL.md +3 -0
- openocr_mlt_cuda-0.4.0/docs/MODELS.md +3 -0
- openocr_mlt_cuda-0.4.0/docs/VALIDATION.md +5 -0
- openocr_mlt_cuda-0.4.0/docs/verification/acceptance-summary.json +48 -0
- openocr_mlt_cuda-0.4.0/docs/verification/fp32-v14-summary.json +268 -0
- openocr_mlt_cuda-0.4.0/examples/demo-crop.png +0 -0
- openocr_mlt_cuda-0.4.0/examples/demo-page.png +0 -0
- openocr_mlt_cuda-0.4.0/examples/ocr_page.py +9 -0
- openocr_mlt_cuda-0.4.0/examples/prepared_ocr.py +13 -0
- openocr_mlt_cuda-0.4.0/examples/recognize.py +8 -0
- openocr_mlt_cuda-0.4.0/pyproject.toml +29 -0
- openocr_mlt_cuda-0.4.0/setup.cfg +4 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/__init__.py +11 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/__main__.py +2 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/api.py +275 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/THIRD_PARTY_NOTICES.txt +26 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/detector-models.json +37 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/dict.txt +19683 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/manifest.json +21 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/model-bundle.json +175 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/onnx-model.json +1565 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/ppocrv6_onnx-LICENSE.txt +21 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets.py +37 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/cli.py +59 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/config.py +45 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/__init__.py +4 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/config.py +34 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/cuda_runtime.py +44 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/db.py +268 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/onnx_backend.py +85 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/geometry.py +37 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/model_assets.py +34 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/model_fetch.py +166 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/onnx_runtime.py +87 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/processing.py +82 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/__init__.py +1 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/cuda_stream.py +39 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/modeling.py +777 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/onnx_backend.py +100 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/partitioned_prefill.py +67 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/postprocess.py +87 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/torch_backend.py +31 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt/types.py +71 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/PKG-INFO +120 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/SOURCES.txt +56 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/dependency_links.txt +1 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/entry_points.txt +2 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/requires.txt +16 -0
- openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/top_level.txt +1 -0
- openocr_mlt_cuda-0.4.0/tools/export_scriptmoe.py +120 -0
- openocr_mlt_cuda-0.4.0/tools/prepare_decode_views.py +44 -0
- openocr_mlt_cuda-0.4.0/tools/prepare_onnx_models.py +4 -0
- openocr_mlt_cuda-0.4.0/tools/prepare_prefill_pipeline.py +79 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openocr-mlt-cuda
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Offline multilingual OCR with ONNX Prefill/Decode recognition and PP-OCRv6 medium detection
|
|
5
|
+
Maintainer: ericleyu
|
|
6
|
+
Project-URL: Models, https://modelscope.cn/models/Strawberry015/openocr-mlt-models
|
|
7
|
+
Project-URL: Model mirror, https://huggingface.co/ericleyu/openocr-mlt-models
|
|
8
|
+
Project-URL: Upstream recognition, https://github.com/YesianRohn/ScriptMoE
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: numpy<2.3,>=2.2
|
|
12
|
+
Requires-Dist: Pillow<12.4,>=12.3
|
|
13
|
+
Requires-Dist: opencv-python-headless<5.1,>=5.0
|
|
14
|
+
Requires-Dist: onnxruntime-gpu==1.20.0
|
|
15
|
+
Requires-Dist: pyclipper==1.4.0
|
|
16
|
+
Requires-Dist: nvidia-cuda-runtime-cu12==12.4.127
|
|
17
|
+
Requires-Dist: nvidia-cublas-cu12==12.4.5.8
|
|
18
|
+
Requires-Dist: nvidia-cudnn-cu12==9.1.0.70
|
|
19
|
+
Requires-Dist: nvidia-cuda-nvrtc-cu12==12.4.127
|
|
20
|
+
Requires-Dist: nvidia-cufft-cu12==11.2.1.3
|
|
21
|
+
Requires-Dist: nvidia-curand-cu12==10.3.5.147
|
|
22
|
+
Provides-Extra: torch
|
|
23
|
+
Requires-Dist: torch<2.6,>=2.5; extra == "torch"
|
|
24
|
+
Requires-Dist: torchvision<0.21,>=0.20; extra == "torch"
|
|
25
|
+
Requires-Dist: safetensors<0.9,>=0.8; extra == "torch"
|
|
26
|
+
|
|
27
|
+
# openocr-mlt
|
|
28
|
+
|
|
29
|
+
Multilingual OCR with ScriptMoE ONNX Prefill/Decode recognition and PP-OCRv6 medium text detection. Run whole-page OCR, detection, or cropped text recognition locally.
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
Validated on Linux x86_64 with Python 3.10.12. Create one virtual environment for the installation you want to use.
|
|
34
|
+
|
|
35
|
+
**CPU**
|
|
36
|
+
|
|
37
|
+
~~~bash
|
|
38
|
+
python3.10 -m venv .venv-ocr-cpu
|
|
39
|
+
source .venv-ocr-cpu/bin/activate
|
|
40
|
+
python -m pip install openocr-mlt
|
|
41
|
+
~~~
|
|
42
|
+
|
|
43
|
+
**NVIDIA CUDA**
|
|
44
|
+
|
|
45
|
+
~~~bash
|
|
46
|
+
python3.10 -m venv .venv-ocr-cuda
|
|
47
|
+
source .venv-ocr-cuda/bin/activate
|
|
48
|
+
python -m pip install openocr-mlt-cuda
|
|
49
|
+
~~~
|
|
50
|
+
|
|
51
|
+
Both packages provide the same Python import and CLI. Install only one package per environment. The CUDA package requires a compatible NVIDIA driver and installs CUDA 12 and cuDNN 9 user-space libraries. ONNX inference runs without PyTorch.
|
|
52
|
+
|
|
53
|
+
### Upgrading from 0.3.0
|
|
54
|
+
|
|
55
|
+
- A 0.3.0 CPU installation can be upgraded with `python -m pip install --upgrade openocr-mlt`.
|
|
56
|
+
- For a 0.3.0 CUDA installation, create a new environment and install `openocr-mlt-cuda` as shown above. The previous `openocr-mlt[cuda]` command applies to 0.3.0. A shared or explicitly configured model cache can be reused.
|
|
57
|
+
|
|
58
|
+
## Python API
|
|
59
|
+
|
|
60
|
+
~~~python
|
|
61
|
+
from openocr_mlt import OpenOCRMLT
|
|
62
|
+
|
|
63
|
+
with OpenOCRMLT(task="ocr") as ocr:
|
|
64
|
+
page = ocr(image_path="page.jpg")
|
|
65
|
+
print(page.text)
|
|
66
|
+
|
|
67
|
+
with OpenOCRMLT(task="det", device="cpu") as detector:
|
|
68
|
+
boxes = detector(image_path="page.jpg")
|
|
69
|
+
print([box.points for box in boxes])
|
|
70
|
+
|
|
71
|
+
with OpenOCRMLT(task="rec", device="cpu") as recognizer:
|
|
72
|
+
lines = recognizer(image_path="crop.jpg")
|
|
73
|
+
print([(line.text, line.score) for line in lines])
|
|
74
|
+
~~~
|
|
75
|
+
|
|
76
|
+
Pass an existing image path or use the image argument with a PIL image or a uint8 NumPy array. Arrays use BGR by default. Pass color_order="RGB" for RGB arrays. The default device is `"auto"`. The CPU installation uses CPU. The CUDA installation uses CUDA when it can initialize the selected models and uses CPU when CUDA is unavailable. Use `device="cpu"` or `device="cuda:0"` to request a specific device. Explicit model directories and the original methods remain supported.
|
|
77
|
+
|
|
78
|
+
## Model preparation
|
|
79
|
+
|
|
80
|
+
The first task call downloads the FP32 model bundle if it is absent from the cache. The bundle is hosted on [ModelScope](https://modelscope.cn/models/Strawberry015/openocr-mlt-models/files). Hugging Face and its mirror are fallback sources. The downloader verifies the archive and all 40 model files before installing the cache. The default cache is `$XDG_CACHE_HOME/openocr-mlt` or `~/.cache/openocr-mlt`. The next task can reuse it offline.
|
|
81
|
+
|
|
82
|
+
Import a local archive in an offline environment with the following command.
|
|
83
|
+
|
|
84
|
+
~~~bash
|
|
85
|
+
python -m openocr_mlt fetch-models \
|
|
86
|
+
--source ./scriptmoe-medium-fp32-20261101-v1.tar.gz --offline
|
|
87
|
+
~~~
|
|
88
|
+
|
|
89
|
+
Set `offline=True` on the Python task to require local assets. The fetch-models command prints the verified recognition and detector directories.
|
|
90
|
+
|
|
91
|
+
## Command line
|
|
92
|
+
|
|
93
|
+
~~~bash
|
|
94
|
+
python -m openocr_mlt fetch-models --cache-dir ./models
|
|
95
|
+
python -m openocr_mlt ocr ./page.jpg \
|
|
96
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
97
|
+
--det-model-dir ./models/scriptmoe-medium-fp32-20261101-v1/ppocrv6-medium-det-bce-v1 \
|
|
98
|
+
--device cpu
|
|
99
|
+
~~~
|
|
100
|
+
|
|
101
|
+
The CLI also supports detect and recognize. Run python -m openocr_mlt --help for the available options.
|
|
102
|
+
|
|
103
|
+
## Model Evaluation
|
|
104
|
+
|
|
105
|
+
The FP32 graphs were evaluated with openocr-mlt 0.3.0.dev14. The model bundle is unchanged.
|
|
106
|
+
|
|
107
|
+
| Task | Data | Result |
|
|
108
|
+
|---|---|---|
|
|
109
|
+
| CUDA recognition | TextMuSS, 10,899 crops | Official normalized weighted accuracy 85.0812%; ten-group macro accuracy 81.0928% |
|
|
110
|
+
| Whole-page OCR, CPU and CUDA | Fixed CC-OCR subset, 200 pages across ten languages, development/held-out split 100/100 | Held-out text F1: macro 72.5849%, micro 79.4545% |
|
|
111
|
+
|
|
112
|
+
Those model evaluations used Linux x86_64, Python 3.10.12, ONNX Runtime 1.20.0, an Intel Xeon Gold 6226R CPU, and an NVIDIA RTX 3090 GPU. One CPU/CUDA recognition whitespace difference was observed on TextMuSS. Additional platforms, hardware and quantized execution remain future work.
|
|
113
|
+
|
|
114
|
+
## Sources
|
|
115
|
+
|
|
116
|
+
- [ScriptMoE](https://github.com/YesianRohn/ScriptMoE): multilingual recognition model and decoding design.
|
|
117
|
+
- [ppocrv6_onnx](https://github.com/AIwork4me/ppocrv6_onnx): detection preprocessing and postprocessing reference.
|
|
118
|
+
- PP-OCRv6 medium: detector distributed through Paddle's official model storage.
|
|
119
|
+
|
|
120
|
+
Component attribution and licensing information are included in the package's THIRD_PARTY_NOTICES.txt and in the model repository's [THIRD_PARTY_NOTICES.md](https://huggingface.co/ericleyu/openocr-mlt-models/blob/7ef39160a893fc7e605e146c1544ba64c1a57f43/THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# openocr-mlt
|
|
2
|
+
|
|
3
|
+
Multilingual OCR with ScriptMoE ONNX Prefill/Decode recognition and PP-OCRv6 medium text detection. Run whole-page OCR, detection, or cropped text recognition locally.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Validated on Linux x86_64 with Python 3.10.12. Create one virtual environment for the installation you want to use.
|
|
8
|
+
|
|
9
|
+
**CPU**
|
|
10
|
+
|
|
11
|
+
~~~bash
|
|
12
|
+
python3.10 -m venv .venv-ocr-cpu
|
|
13
|
+
source .venv-ocr-cpu/bin/activate
|
|
14
|
+
python -m pip install openocr-mlt
|
|
15
|
+
~~~
|
|
16
|
+
|
|
17
|
+
**NVIDIA CUDA**
|
|
18
|
+
|
|
19
|
+
~~~bash
|
|
20
|
+
python3.10 -m venv .venv-ocr-cuda
|
|
21
|
+
source .venv-ocr-cuda/bin/activate
|
|
22
|
+
python -m pip install openocr-mlt-cuda
|
|
23
|
+
~~~
|
|
24
|
+
|
|
25
|
+
Both packages provide the same Python import and CLI. Install only one package per environment. The CUDA package requires a compatible NVIDIA driver and installs CUDA 12 and cuDNN 9 user-space libraries. ONNX inference runs without PyTorch.
|
|
26
|
+
|
|
27
|
+
### Upgrading from 0.3.0
|
|
28
|
+
|
|
29
|
+
- A 0.3.0 CPU installation can be upgraded with `python -m pip install --upgrade openocr-mlt`.
|
|
30
|
+
- For a 0.3.0 CUDA installation, create a new environment and install `openocr-mlt-cuda` as shown above. The previous `openocr-mlt[cuda]` command applies to 0.3.0. A shared or explicitly configured model cache can be reused.
|
|
31
|
+
|
|
32
|
+
## Python API
|
|
33
|
+
|
|
34
|
+
~~~python
|
|
35
|
+
from openocr_mlt import OpenOCRMLT
|
|
36
|
+
|
|
37
|
+
with OpenOCRMLT(task="ocr") as ocr:
|
|
38
|
+
page = ocr(image_path="page.jpg")
|
|
39
|
+
print(page.text)
|
|
40
|
+
|
|
41
|
+
with OpenOCRMLT(task="det", device="cpu") as detector:
|
|
42
|
+
boxes = detector(image_path="page.jpg")
|
|
43
|
+
print([box.points for box in boxes])
|
|
44
|
+
|
|
45
|
+
with OpenOCRMLT(task="rec", device="cpu") as recognizer:
|
|
46
|
+
lines = recognizer(image_path="crop.jpg")
|
|
47
|
+
print([(line.text, line.score) for line in lines])
|
|
48
|
+
~~~
|
|
49
|
+
|
|
50
|
+
Pass an existing image path or use the image argument with a PIL image or a uint8 NumPy array. Arrays use BGR by default. Pass color_order="RGB" for RGB arrays. The default device is `"auto"`. The CPU installation uses CPU. The CUDA installation uses CUDA when it can initialize the selected models and uses CPU when CUDA is unavailable. Use `device="cpu"` or `device="cuda:0"` to request a specific device. Explicit model directories and the original methods remain supported.
|
|
51
|
+
|
|
52
|
+
## Model preparation
|
|
53
|
+
|
|
54
|
+
The first task call downloads the FP32 model bundle if it is absent from the cache. The bundle is hosted on [ModelScope](https://modelscope.cn/models/Strawberry015/openocr-mlt-models/files). Hugging Face and its mirror are fallback sources. The downloader verifies the archive and all 40 model files before installing the cache. The default cache is `$XDG_CACHE_HOME/openocr-mlt` or `~/.cache/openocr-mlt`. The next task can reuse it offline.
|
|
55
|
+
|
|
56
|
+
Import a local archive in an offline environment with the following command.
|
|
57
|
+
|
|
58
|
+
~~~bash
|
|
59
|
+
python -m openocr_mlt fetch-models \
|
|
60
|
+
--source ./scriptmoe-medium-fp32-20261101-v1.tar.gz --offline
|
|
61
|
+
~~~
|
|
62
|
+
|
|
63
|
+
Set `offline=True` on the Python task to require local assets. The fetch-models command prints the verified recognition and detector directories.
|
|
64
|
+
|
|
65
|
+
## Command line
|
|
66
|
+
|
|
67
|
+
~~~bash
|
|
68
|
+
python -m openocr_mlt fetch-models --cache-dir ./models
|
|
69
|
+
python -m openocr_mlt ocr ./page.jpg \
|
|
70
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
71
|
+
--det-model-dir ./models/scriptmoe-medium-fp32-20261101-v1/ppocrv6-medium-det-bce-v1 \
|
|
72
|
+
--device cpu
|
|
73
|
+
~~~
|
|
74
|
+
|
|
75
|
+
The CLI also supports detect and recognize. Run python -m openocr_mlt --help for the available options.
|
|
76
|
+
|
|
77
|
+
## Model Evaluation
|
|
78
|
+
|
|
79
|
+
The FP32 graphs were evaluated with openocr-mlt 0.3.0.dev14. The model bundle is unchanged.
|
|
80
|
+
|
|
81
|
+
| Task | Data | Result |
|
|
82
|
+
|---|---|---|
|
|
83
|
+
| CUDA recognition | TextMuSS, 10,899 crops | Official normalized weighted accuracy 85.0812%; ten-group macro accuracy 81.0928% |
|
|
84
|
+
| Whole-page OCR, CPU and CUDA | Fixed CC-OCR subset, 200 pages across ten languages, development/held-out split 100/100 | Held-out text F1: macro 72.5849%, micro 79.4545% |
|
|
85
|
+
|
|
86
|
+
Those model evaluations used Linux x86_64, Python 3.10.12, ONNX Runtime 1.20.0, an Intel Xeon Gold 6226R CPU, and an NVIDIA RTX 3090 GPU. One CPU/CUDA recognition whitespace difference was observed on TextMuSS. Additional platforms, hardware and quantized execution remain future work.
|
|
87
|
+
|
|
88
|
+
## Sources
|
|
89
|
+
|
|
90
|
+
- [ScriptMoE](https://github.com/YesianRohn/ScriptMoE): multilingual recognition model and decoding design.
|
|
91
|
+
- [ppocrv6_onnx](https://github.com/AIwork4me/ppocrv6_onnx): detection preprocessing and postprocessing reference.
|
|
92
|
+
- PP-OCRv6 medium: detector distributed through Paddle's official model storage.
|
|
93
|
+
|
|
94
|
+
Component attribution and licensing information are included in the package's THIRD_PARTY_NOTICES.txt and in the model repository's [THIRD_PARTY_NOTICES.md](https://huggingface.co/ericleyu/openocr-mlt-models/blob/7ef39160a893fc7e605e146c1544ba64c1a57f43/THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Third-Party Model Sources and Licensing
|
|
2
|
+
|
|
3
|
+
## ScriptMoE Recognition
|
|
4
|
+
|
|
5
|
+
Recognition models are derived from [ScriptMoE](https://github.com/YesianRohn/ScriptMoE) at upstream revision `5dde99867aaee6b4af3e75a3020b225eab17ac53`. ONNX conversion preserves the character dictionary and autoregressive decoding rules and uses KV caching and optimized MoE execution.
|
|
6
|
+
|
|
7
|
+
| Artifact | SHA256 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| Original recognition weights | 60c74a924404b652c3a9550ec370c74d78850151785341729bdac268c014650d |
|
|
10
|
+
| Character dictionary | 7b4eb2ca5fd6c9b6c6ecf423f69d35d8da48088697303e53624af196ee9ab6c0 |
|
|
11
|
+
|
|
12
|
+
## PP-OCRv6 Medium Detection
|
|
13
|
+
|
|
14
|
+
The detector is distributed by Paddle as [PP-OCRv6_medium_det_onnx.tar](https://paddle-model-ecology.bj.bcebos.com/paddlex/official_inference_model/paddle3.0.0/tmp/PP-OCRv6_medium_det_onnx.tar).
|
|
15
|
+
|
|
16
|
+
| Property | Value |
|
|
17
|
+
|---|---|
|
|
18
|
+
| File | inference.onnx |
|
|
19
|
+
| Size | 62,026,563 bytes |
|
|
20
|
+
| SHA256 | a0d14865d3a297970899b5c246f0e47c43879bb406c3a1fa4e505aba84b134e4 |
|
|
21
|
+
|
|
22
|
+
The accompanying Python package adapts detection preprocessing and postprocessing from [ppocrv6_onnx](https://github.com/AIwork4me/ppocrv6_onnx), revision `d638eb0bb5d8222522abcc1bae4394cbeeb636f0`, under its MIT license. The package includes the license text for that code.
|
|
23
|
+
|
|
24
|
+
## Licensing Status
|
|
25
|
+
|
|
26
|
+
A unified redistribution license has not been specified for this combined model bundle. The MIT license of the detection adapter applies to that code; model weights have separate licensing requirements.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Validation
|
|
2
|
+
|
|
3
|
+
The FP32 model and inference implementation in this release use the same pipeline evaluated with version 0.3.0.dev14. See the [evaluation summary](verification/fp32-v14-summary.json) for the historical TextMuSS and CC-OCR quality and performance results.
|
|
4
|
+
|
|
5
|
+
The [installation record](verification/acceptance-summary.json) describes the earlier 0.3.0.dev15 trial. It covers separate Linux x86_64 CPU/CUDA installations, model import, cache reuse, whole-page OCR and cropped recognition.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.3.0.dev15",
|
|
3
|
+
"date": "2026-11-01",
|
|
4
|
+
"passed": true,
|
|
5
|
+
"public_release": false,
|
|
6
|
+
"public_model_url_configured": false,
|
|
7
|
+
"cpu_cuda_clean_installs": [
|
|
8
|
+
{
|
|
9
|
+
"kind": "cpu",
|
|
10
|
+
"python": "3.10.12 (main, Aug 31 2026, 10:18:17) [GCC 11.4.0]",
|
|
11
|
+
"packages": 13,
|
|
12
|
+
"version": "0.3.0.dev15",
|
|
13
|
+
"pip_check": true,
|
|
14
|
+
"model_files": 40,
|
|
15
|
+
"cache_reused": true,
|
|
16
|
+
"page_text": "Security",
|
|
17
|
+
"crop_text": "Security",
|
|
18
|
+
"actual_rec_device": "cpu",
|
|
19
|
+
"actual_det_device": "cpu",
|
|
20
|
+
"invalid_device_exit": 2
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"kind": "cuda",
|
|
24
|
+
"python": "3.10.12 (main, Aug 31 2026, 10:18:17) [GCC 11.4.0]",
|
|
25
|
+
"packages": 19,
|
|
26
|
+
"version": "0.3.0.dev15",
|
|
27
|
+
"pip_check": true,
|
|
28
|
+
"model_files": 40,
|
|
29
|
+
"cache_reused": true,
|
|
30
|
+
"page_text": "Security",
|
|
31
|
+
"crop_text": "Security",
|
|
32
|
+
"actual_rec_device": "cuda:0",
|
|
33
|
+
"actual_det_device": "cuda:0",
|
|
34
|
+
"invalid_device_exit": 2
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"unit_boundary_tests": 12,
|
|
38
|
+
"https_test": "isolated transport/redirect tests; no public endpoint configured",
|
|
39
|
+
"sdist_runtime_files_identical": 31,
|
|
40
|
+
"hash_lock_dry_run_resolved": {
|
|
41
|
+
"cpu": 13,
|
|
42
|
+
"cuda": 19
|
|
43
|
+
},
|
|
44
|
+
"inference_modules_and_models_identical_to": "0.3.0.dev14",
|
|
45
|
+
"new_full_quality_runs": 0,
|
|
46
|
+
"new_performance_runs": 0,
|
|
47
|
+
"prior_evidence": "fp32-v14-summary.json"
|
|
48
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.3.0.dev14",
|
|
3
|
+
"date": "2026-11-01",
|
|
4
|
+
"recognition_model_id": "scriptmoe-onnx-fp32-v9",
|
|
5
|
+
"detector": "PP-OCRv6 medium ONNX",
|
|
6
|
+
"recognition": {
|
|
7
|
+
"cuda": {
|
|
8
|
+
"samples": 10899,
|
|
9
|
+
"failed": 0,
|
|
10
|
+
"skipped": 0,
|
|
11
|
+
"text_differences": 0,
|
|
12
|
+
"raw_text_differences": 0,
|
|
13
|
+
"termination_differences": 0,
|
|
14
|
+
"decoded_steps_differences": 0,
|
|
15
|
+
"filtered_exact_accuracy": 0.7975961097348381,
|
|
16
|
+
"max_score_difference": 8.195638656616211e-05,
|
|
17
|
+
"official_weighted_accuracy": 0.850812001101018,
|
|
18
|
+
"official_ten_group_macro": 0.8109283048360594,
|
|
19
|
+
"tested_package_version": "0.3.0.dev14"
|
|
20
|
+
},
|
|
21
|
+
"cpu": {
|
|
22
|
+
"samples": 10899,
|
|
23
|
+
"failed": 0,
|
|
24
|
+
"skipped": 0,
|
|
25
|
+
"text_differences": 1,
|
|
26
|
+
"raw_text_differences": 1,
|
|
27
|
+
"termination_differences": 0,
|
|
28
|
+
"decoded_steps_differences": 1,
|
|
29
|
+
"filtered_exact_accuracy": 0.7975043581979998,
|
|
30
|
+
"max_score_difference": 0.01205642976694632,
|
|
31
|
+
"official_weighted_accuracy": 0.850812001101018,
|
|
32
|
+
"official_ten_group_macro": 0.8109283048360594,
|
|
33
|
+
"tested_package_version": "0.3.0.dev13",
|
|
34
|
+
"applies_to": "0.3.0.dev14",
|
|
35
|
+
"cpu_code_and_models_identical": true,
|
|
36
|
+
"same_cpu_reference": "0.3.0.dev8",
|
|
37
|
+
"same_cpu_text_steps_eos_score_differences": 0,
|
|
38
|
+
"installed_current_version_regression_samples": 300
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"cc_ocr": {
|
|
42
|
+
"dev": {
|
|
43
|
+
"images": 100,
|
|
44
|
+
"macro_f1": 0.7131863812825354,
|
|
45
|
+
"micro_f1": 0.8140047618306818
|
|
46
|
+
},
|
|
47
|
+
"eval": {
|
|
48
|
+
"images": 100,
|
|
49
|
+
"macro_f1": 0.7258491279221538,
|
|
50
|
+
"micro_f1": 0.7945454540507626
|
|
51
|
+
},
|
|
52
|
+
"images": 200,
|
|
53
|
+
"boxes": 1957,
|
|
54
|
+
"failed": 0,
|
|
55
|
+
"skipped": 0,
|
|
56
|
+
"page_text_differences": 0,
|
|
57
|
+
"raw_text_differences": 0,
|
|
58
|
+
"detection_differences": 0,
|
|
59
|
+
"decoding_contract_differences": 0
|
|
60
|
+
},
|
|
61
|
+
"performance": {
|
|
62
|
+
"cuda_whole_page": {
|
|
63
|
+
"rounds": 3,
|
|
64
|
+
"samples_per_backend": 24,
|
|
65
|
+
"pairs": [
|
|
66
|
+
{
|
|
67
|
+
"round": 1,
|
|
68
|
+
"torch_ms": 1124.4756288360804,
|
|
69
|
+
"onnx_ms": 921.554900589399,
|
|
70
|
+
"ratio": 1.2201938572698157
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"round": 2,
|
|
74
|
+
"torch_ms": 983.9565325528383,
|
|
75
|
+
"onnx_ms": 913.2588730426505,
|
|
76
|
+
"ratio": 1.0774125076657055
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"round": 3,
|
|
80
|
+
"torch_ms": 1038.3566328091547,
|
|
81
|
+
"onnx_ms": 953.9304067147896,
|
|
82
|
+
"ratio": 1.0885035485818277
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"mean_ms": {
|
|
86
|
+
"torch": 1048.9295980660245,
|
|
87
|
+
"onnx": 929.5813934489464
|
|
88
|
+
},
|
|
89
|
+
"round_mean_stdev_ms": {
|
|
90
|
+
"torch": 70.85368586606485,
|
|
91
|
+
"onnx": 21.490971442195402
|
|
92
|
+
},
|
|
93
|
+
"ratio": 1.128389192660441,
|
|
94
|
+
"text_differences": [],
|
|
95
|
+
"scope": "same medium+same8 CC-OCR eval pages+sameGPU,three alternating pairs; no broad full-CC speed claim"
|
|
96
|
+
},
|
|
97
|
+
"cpu_cropped_recognition": {
|
|
98
|
+
"rounds": 3,
|
|
99
|
+
"samples_per_backend": 60,
|
|
100
|
+
"pairs": [
|
|
101
|
+
{
|
|
102
|
+
"round": 1,
|
|
103
|
+
"torch_ms": 133.5505000781268,
|
|
104
|
+
"onnx_ms": 133.87302686460316,
|
|
105
|
+
"ratio": 0.9975908008205224
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"round": 2,
|
|
109
|
+
"torch_ms": 180.9673246461898,
|
|
110
|
+
"onnx_ms": 178.97417438216507,
|
|
111
|
+
"ratio": 1.0111365244226171
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"round": 3,
|
|
115
|
+
"torch_ms": 178.60913323238492,
|
|
116
|
+
"onnx_ms": 178.6530858837068,
|
|
117
|
+
"ratio": 0.9997539776539293
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"mean_ms": {
|
|
121
|
+
"torch": 164.37565265223384,
|
|
122
|
+
"onnx": 163.8334290434917
|
|
123
|
+
},
|
|
124
|
+
"ratio": 1.003309603002927,
|
|
125
|
+
"text_differences": [],
|
|
126
|
+
"scope": "cropped-recognition only, fixed20,three alternating pairs; not CPU whole-page or full-set performance"
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"environment": {
|
|
130
|
+
"os": "Linux x86_64",
|
|
131
|
+
"glibc": "2.35",
|
|
132
|
+
"python": "3.10.12",
|
|
133
|
+
"onnxruntime": "1.20.0",
|
|
134
|
+
"numpy": "2.2.6",
|
|
135
|
+
"opencv_python_headless": "5.0.0.93",
|
|
136
|
+
"cpu": "Xeon Gold 6226R",
|
|
137
|
+
"gpu": "RTX 3090",
|
|
138
|
+
"driver": "575.57.08",
|
|
139
|
+
"cuda_runtime": "12.4.127",
|
|
140
|
+
"cudnn": "9.1.0.70"
|
|
141
|
+
},
|
|
142
|
+
"installation": {
|
|
143
|
+
"independent_cpu_cuda": true,
|
|
144
|
+
"torch": false,
|
|
145
|
+
"outside_source_directory": true,
|
|
146
|
+
"hash_locked_offline_install": true,
|
|
147
|
+
"sdist_runtime_files_equal": 29,
|
|
148
|
+
"model_prepared_ordinary_files": 40,
|
|
149
|
+
"persistent_real_ocr_examples": true,
|
|
150
|
+
"complete_offline_dependencies_in_zip": false
|
|
151
|
+
},
|
|
152
|
+
"wheel": {
|
|
153
|
+
"name": "openocr_mlt-0.3.0.dev14-py3-none-any.whl",
|
|
154
|
+
"bytes": 88248,
|
|
155
|
+
"sha256": "f5bcfbc81750b87b35ff0948459866f3c054cf6f8b2b1f29af99a2b32ebf0fea"
|
|
156
|
+
},
|
|
157
|
+
"sdist": {
|
|
158
|
+
"name": "openocr_mlt-0.3.0.dev14.tar.gz",
|
|
159
|
+
"bytes": 91909,
|
|
160
|
+
"sha256": "34aa38f1732e7d6d81712c80d7e9886ac718293b23bba3cb2500036876fad960"
|
|
161
|
+
},
|
|
162
|
+
"cpu_whole_page": {
|
|
163
|
+
"version": "0.3.0.dev14",
|
|
164
|
+
"scope": "CPU detection and CPU recognition, fixed nonrandom CC-OCR200,10 languages20 each; not full CC-OCR or detection Hmean",
|
|
165
|
+
"quality": {
|
|
166
|
+
"pages": 200,
|
|
167
|
+
"boxes": 1957,
|
|
168
|
+
"failed": 0,
|
|
169
|
+
"skipped": 0,
|
|
170
|
+
"crop_errors": 0,
|
|
171
|
+
"same_cpu_comparison": {
|
|
172
|
+
"passed": true,
|
|
173
|
+
"pages": 200,
|
|
174
|
+
"boxes": 1957,
|
|
175
|
+
"different_pages": 0,
|
|
176
|
+
"differences_by_page": {
|
|
177
|
+
"page_text": 0,
|
|
178
|
+
"detections": 0,
|
|
179
|
+
"raw_text": 0,
|
|
180
|
+
"filtered_text": 0,
|
|
181
|
+
"termination": 0,
|
|
182
|
+
"decoded_steps": 0,
|
|
183
|
+
"status": 0
|
|
184
|
+
},
|
|
185
|
+
"max_rec_score_difference": 1.7285346984863281e-06
|
|
186
|
+
},
|
|
187
|
+
"max_detection_score_difference": 0.0,
|
|
188
|
+
"metrics": {
|
|
189
|
+
"torch": {
|
|
190
|
+
"dev": {
|
|
191
|
+
"images": 100,
|
|
192
|
+
"macro_f1": 0.7131863812825354,
|
|
193
|
+
"micro_f1": 0.8140047618306818
|
|
194
|
+
},
|
|
195
|
+
"eval": {
|
|
196
|
+
"images": 100,
|
|
197
|
+
"macro_f1": 0.7258491279221538,
|
|
198
|
+
"micro_f1": 0.7945454540507626
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"onnx": {
|
|
202
|
+
"dev": {
|
|
203
|
+
"images": 100,
|
|
204
|
+
"macro_f1": 0.7131863812825354,
|
|
205
|
+
"micro_f1": 0.8140047618306818
|
|
206
|
+
},
|
|
207
|
+
"eval": {
|
|
208
|
+
"images": 100,
|
|
209
|
+
"macro_f1": 0.7258491279221538,
|
|
210
|
+
"micro_f1": 0.7945454540507626
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
"cross_device_observation": {
|
|
215
|
+
"reference": "frozen CUDA, same fixed200",
|
|
216
|
+
"different_page_texts": 0
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"performance": {
|
|
220
|
+
"rounds": 3,
|
|
221
|
+
"samples_per_backend": 24,
|
|
222
|
+
"pairs": [
|
|
223
|
+
{
|
|
224
|
+
"round": 1,
|
|
225
|
+
"torch_ms": 15015.680243377574,
|
|
226
|
+
"onnx_ms": 14303.62608062569,
|
|
227
|
+
"ratio": 1.0497813742290398
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
"round": 2,
|
|
231
|
+
"torch_ms": 15510.577811743133,
|
|
232
|
+
"onnx_ms": 15171.641253167763,
|
|
233
|
+
"ratio": 1.0223401379534072
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
"round": 3,
|
|
237
|
+
"torch_ms": 15150.97376552876,
|
|
238
|
+
"onnx_ms": 14863.175587030128,
|
|
239
|
+
"ratio": 1.0193631688472933
|
|
240
|
+
}
|
|
241
|
+
],
|
|
242
|
+
"mean_ms": {
|
|
243
|
+
"torch": 15225.74394021649,
|
|
244
|
+
"onnx": 14779.48097360786
|
|
245
|
+
},
|
|
246
|
+
"ratio": 1.0301947657976307,
|
|
247
|
+
"all_output_comparisons_passed": true
|
|
248
|
+
},
|
|
249
|
+
"runtime_versions": {
|
|
250
|
+
"torch": {
|
|
251
|
+
"numpy": "2.2.6",
|
|
252
|
+
"Pillow": "12.3.0",
|
|
253
|
+
"opencv-python-headless": "5.0.0.93",
|
|
254
|
+
"onnxruntime": "1.20.0",
|
|
255
|
+
"torch": "2.5.1+cpu"
|
|
256
|
+
},
|
|
257
|
+
"onnx": {
|
|
258
|
+
"numpy": "2.2.6",
|
|
259
|
+
"Pillow": "12.3.0",
|
|
260
|
+
"opencv-python-headless": "5.0.0.93",
|
|
261
|
+
"onnxruntime": "1.20.0"
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
"frozen_wheel_sha256": "f5bcfbc81750b87b35ff0948459866f3c054cf6f8b2b1f29af99a2b32ebf0fea"
|
|
265
|
+
},
|
|
266
|
+
"documentation_updated": "2026-11-01",
|
|
267
|
+
"prior_frozen_evidence_date": "2026-10-31"
|
|
268
|
+
}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Run complete page OCR with CPU or CUDA ONNX."""
|
|
2
|
+
import argparse,json
|
|
3
|
+
from openocr_mlt import OpenOCRMLT
|
|
4
|
+
p=argparse.ArgumentParser()
|
|
5
|
+
p.add_argument("--model-dir",required=True);p.add_argument("--det-model-dir",required=True)
|
|
6
|
+
p.add_argument("--image",required=True);p.add_argument("--device",default="cpu")
|
|
7
|
+
a=p.parse_args()
|
|
8
|
+
with OpenOCRMLT(model_dir=a.model_dir,det_model_dir=a.det_model_dir,device=a.device) as ocr:
|
|
9
|
+
print(json.dumps(ocr.ocr(a.image).to_dict(),ensure_ascii=False))
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Prepare the pinned models, then run one page."""
|
|
2
|
+
import argparse,json
|
|
3
|
+
from openocr_mlt import OpenOCRMLT,fetch_models
|
|
4
|
+
p=argparse.ArgumentParser()
|
|
5
|
+
p.add_argument("--bundle",help="Local bundle path or distributor-provided HTTPS URL")
|
|
6
|
+
p.add_argument("--cache-dir",default="./models-cache")
|
|
7
|
+
p.add_argument("--offline",action="store_true")
|
|
8
|
+
p.add_argument("--image",required=True)
|
|
9
|
+
p.add_argument("--device",default="cpu")
|
|
10
|
+
a=p.parse_args()
|
|
11
|
+
paths=fetch_models(source=a.bundle,cache_dir=a.cache_dir,offline=a.offline)
|
|
12
|
+
with OpenOCRMLT(model_dir=paths["recognition_dir"],det_model_dir=paths["detector_dir"],device=a.device) as engine:
|
|
13
|
+
print(json.dumps(engine.ocr(a.image).to_dict(),ensure_ascii=False))
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""Run the installed package from any working directory."""
|
|
2
|
+
import argparse,json
|
|
3
|
+
from openocr_mlt import OpenOCRMLT
|
|
4
|
+
p=argparse.ArgumentParser()
|
|
5
|
+
p.add_argument("--model-dir",required=True);p.add_argument("--image",required=True);p.add_argument("--device",default="cpu")
|
|
6
|
+
a=p.parse_args()
|
|
7
|
+
with OpenOCRMLT(model_dir=a.model_dir,device=a.device) as ocr:
|
|
8
|
+
print(json.dumps(ocr.recognize(a.image)[0].to_dict(),ensure_ascii=False))
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires=["setuptools>=77"]
|
|
3
|
+
build-backend="setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name="openocr-mlt-cuda"
|
|
7
|
+
version="0.4.0"
|
|
8
|
+
maintainers=[{name="ericleyu"}]
|
|
9
|
+
description="Offline multilingual OCR with ONNX Prefill/Decode recognition and PP-OCRv6 medium detection"
|
|
10
|
+
readme="README.md"
|
|
11
|
+
requires-python=">=3.10"
|
|
12
|
+
dependencies=["numpy>=2.2,<2.3","Pillow>=12.3,<12.4","opencv-python-headless>=5.0,<5.1","onnxruntime-gpu==1.20.0","pyclipper==1.4.0","nvidia-cuda-runtime-cu12==12.4.127","nvidia-cublas-cu12==12.4.5.8","nvidia-cudnn-cu12==9.1.0.70","nvidia-cuda-nvrtc-cu12==12.4.127","nvidia-cufft-cu12==11.2.1.3","nvidia-curand-cu12==10.3.5.147"]
|
|
13
|
+
|
|
14
|
+
[project.optional-dependencies]
|
|
15
|
+
torch=["torch>=2.5,<2.6","torchvision>=0.20,<0.21","safetensors>=0.8,<0.9"]
|
|
16
|
+
|
|
17
|
+
[project.urls]
|
|
18
|
+
Models="https://modelscope.cn/models/Strawberry015/openocr-mlt-models"
|
|
19
|
+
"Model mirror"="https://huggingface.co/ericleyu/openocr-mlt-models"
|
|
20
|
+
"Upstream recognition"="https://github.com/YesianRohn/ScriptMoE"
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
openocr-mlt="openocr_mlt.cli:main"
|
|
24
|
+
|
|
25
|
+
[tool.setuptools.packages.find]
|
|
26
|
+
where=["src"]
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.package-data]
|
|
29
|
+
openocr_mlt=["assets/*.txt","assets/*.json"]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""Offline, serial, FP32 ScriptMoE recognition."""
|
|
2
|
+
from .api import OpenOCRMLT
|
|
3
|
+
from .config import RecognitionConfig
|
|
4
|
+
from .types import RecognitionResult, DetectionResult, OCRLine, OCRResult
|
|
5
|
+
from .detection import TextDetector, DetectionConfig
|
|
6
|
+
|
|
7
|
+
__version__ = "0.4.0"
|
|
8
|
+
__all__ = ["OpenOCRMLT", "RecognitionConfig", "RecognitionResult", "DetectionResult", "OCRLine", "OCRResult", "TextDetector", "DetectionConfig"]
|
|
9
|
+
|
|
10
|
+
from .model_fetch import fetch_models
|
|
11
|
+
__all__.append("fetch_models")
|