openocr-mlt 0.3.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-0.3.0/MANIFEST.in +7 -0
- openocr_mlt-0.3.0/PKG-INFO +149 -0
- openocr_mlt-0.3.0/README.md +120 -0
- openocr_mlt-0.3.0/THIRD_PARTY_NOTICES.md +26 -0
- openocr_mlt-0.3.0/docs/INSTALL.md +9 -0
- openocr_mlt-0.3.0/docs/MODELS.md +5 -0
- openocr_mlt-0.3.0/docs/VALIDATION.md +5 -0
- openocr_mlt-0.3.0/docs/verification/acceptance-summary.json +48 -0
- openocr_mlt-0.3.0/docs/verification/fp32-v14-summary.json +268 -0
- openocr_mlt-0.3.0/examples/demo-crop.png +0 -0
- openocr_mlt-0.3.0/examples/demo-page.png +0 -0
- openocr_mlt-0.3.0/examples/ocr_page.py +9 -0
- openocr_mlt-0.3.0/examples/prepared_ocr.py +13 -0
- openocr_mlt-0.3.0/examples/recognize.py +8 -0
- openocr_mlt-0.3.0/pyproject.toml +30 -0
- openocr_mlt-0.3.0/setup.cfg +4 -0
- openocr_mlt-0.3.0/src/openocr_mlt/__init__.py +11 -0
- openocr_mlt-0.3.0/src/openocr_mlt/__main__.py +2 -0
- openocr_mlt-0.3.0/src/openocr_mlt/api.py +144 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/THIRD_PARTY_NOTICES.txt +26 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/detector-models.json +37 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/dict.txt +19683 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/manifest.json +21 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/model-bundle.json +171 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/onnx-model.json +1565 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets/ppocrv6_onnx-LICENSE.txt +21 -0
- openocr_mlt-0.3.0/src/openocr_mlt/assets.py +37 -0
- openocr_mlt-0.3.0/src/openocr_mlt/cli.py +59 -0
- openocr_mlt-0.3.0/src/openocr_mlt/config.py +45 -0
- openocr_mlt-0.3.0/src/openocr_mlt/detection/__init__.py +4 -0
- openocr_mlt-0.3.0/src/openocr_mlt/detection/config.py +34 -0
- openocr_mlt-0.3.0/src/openocr_mlt/detection/cuda_runtime.py +44 -0
- openocr_mlt-0.3.0/src/openocr_mlt/detection/db.py +268 -0
- openocr_mlt-0.3.0/src/openocr_mlt/detection/onnx_backend.py +85 -0
- openocr_mlt-0.3.0/src/openocr_mlt/geometry.py +37 -0
- openocr_mlt-0.3.0/src/openocr_mlt/model_assets.py +34 -0
- openocr_mlt-0.3.0/src/openocr_mlt/model_fetch.py +144 -0
- openocr_mlt-0.3.0/src/openocr_mlt/onnx_runtime.py +74 -0
- openocr_mlt-0.3.0/src/openocr_mlt/processing.py +82 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/__init__.py +1 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/cuda_stream.py +39 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/modeling.py +777 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/onnx_backend.py +100 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/partitioned_prefill.py +67 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/postprocess.py +87 -0
- openocr_mlt-0.3.0/src/openocr_mlt/recognition/torch_backend.py +31 -0
- openocr_mlt-0.3.0/src/openocr_mlt/types.py +71 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/PKG-INFO +149 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/SOURCES.txt +56 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/dependency_links.txt +1 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/entry_points.txt +2 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/requires.txt +22 -0
- openocr_mlt-0.3.0/src/openocr_mlt.egg-info/top_level.txt +1 -0
- openocr_mlt-0.3.0/tools/export_scriptmoe.py +120 -0
- openocr_mlt-0.3.0/tools/prepare_decode_views.py +44 -0
- openocr_mlt-0.3.0/tools/prepare_onnx_models.py +4 -0
- openocr_mlt-0.3.0/tools/prepare_prefill_pipeline.py +79 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: openocr-mlt
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Offline multilingual OCR with ONNX Prefill/Decode recognition and PP-OCRv6 medium detection
|
|
5
|
+
Maintainer: ericleyu
|
|
6
|
+
Project-URL: Models, https://huggingface.co/ericleyu/openocr-mlt-models
|
|
7
|
+
Project-URL: Upstream recognition, https://github.com/YesianRohn/ScriptMoE
|
|
8
|
+
Requires-Python: >=3.10
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
Requires-Dist: numpy<2.3,>=2.2
|
|
11
|
+
Requires-Dist: Pillow<12.4,>=12.3
|
|
12
|
+
Requires-Dist: opencv-python-headless<5.1,>=5.0
|
|
13
|
+
Provides-Extra: cpu
|
|
14
|
+
Requires-Dist: onnxruntime==1.20.0; extra == "cpu"
|
|
15
|
+
Requires-Dist: pyclipper==1.4.0; extra == "cpu"
|
|
16
|
+
Provides-Extra: cuda
|
|
17
|
+
Requires-Dist: onnxruntime-gpu==1.20.0; extra == "cuda"
|
|
18
|
+
Requires-Dist: pyclipper==1.4.0; extra == "cuda"
|
|
19
|
+
Requires-Dist: nvidia-cuda-runtime-cu12==12.4.127; extra == "cuda"
|
|
20
|
+
Requires-Dist: nvidia-cublas-cu12==12.4.5.8; extra == "cuda"
|
|
21
|
+
Requires-Dist: nvidia-cudnn-cu12==9.1.0.70; extra == "cuda"
|
|
22
|
+
Requires-Dist: nvidia-cuda-nvrtc-cu12==12.4.127; extra == "cuda"
|
|
23
|
+
Requires-Dist: nvidia-cufft-cu12==11.2.1.3; extra == "cuda"
|
|
24
|
+
Requires-Dist: nvidia-curand-cu12==10.3.5.147; extra == "cuda"
|
|
25
|
+
Provides-Extra: torch
|
|
26
|
+
Requires-Dist: torch<2.6,>=2.5; extra == "torch"
|
|
27
|
+
Requires-Dist: torchvision<0.21,>=0.20; extra == "torch"
|
|
28
|
+
Requires-Dist: safetensors<0.9,>=0.8; extra == "torch"
|
|
29
|
+
|
|
30
|
+
# openocr-mlt
|
|
31
|
+
|
|
32
|
+
Multilingual OCR with ScriptMoE recognition and PP-OCRv6 medium text detection. The package provides cropped text recognition, whole-page OCR, a Python API, and a command-line interface.
|
|
33
|
+
|
|
34
|
+
Both models run with ONNX Runtime. Recognition uses autoregressive Prefill/Decode and KV caching. CPU and CUDA installations use separate runtime dependencies.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
Use Linux x86_64 with Python 3.10.12 for the verified installation path. Select the CPU or CUDA extra in a virtual environment.
|
|
39
|
+
|
|
40
|
+
~~~bash
|
|
41
|
+
python3.10 -m venv .venv-cpu
|
|
42
|
+
.venv-cpu/bin/python -m pip install "openocr-mlt[cpu]"
|
|
43
|
+
~~~
|
|
44
|
+
|
|
45
|
+
For CUDA, use a separate environment:
|
|
46
|
+
|
|
47
|
+
~~~bash
|
|
48
|
+
python3.10 -m venv .venv-cuda
|
|
49
|
+
.venv-cuda/bin/python -m pip install "openocr-mlt[cuda]"
|
|
50
|
+
~~~
|
|
51
|
+
|
|
52
|
+
The CPU extra installs ONNX Runtime; the CUDA extra installs ONNX Runtime GPU and the required CUDA 12/cuDNN 9 user-space libraries. CUDA requires an NVIDIA driver. PyTorch is not required for ONNX inference. Install the CPU and CUDA extras in separate environments.
|
|
53
|
+
|
|
54
|
+
## Model Preparation
|
|
55
|
+
|
|
56
|
+
Activate the environment you installed, for example `source .venv-cpu/bin/activate`.
|
|
57
|
+
|
|
58
|
+
Download and verify the registered model bundle:
|
|
59
|
+
|
|
60
|
+
~~~bash
|
|
61
|
+
python -m openocr_mlt fetch-models --cache-dir ./models
|
|
62
|
+
~~~
|
|
63
|
+
|
|
64
|
+
Activate the selected virtual environment before running these commands. The command downloads the pinned FP32 bundle, verifies the archive and 40 model files, and returns the recognition and detector directories. Subsequent calls verify and reuse the cache.
|
|
65
|
+
|
|
66
|
+
The bundle is 213,794,128 bytes and is hosted in [ericleyu/openocr-mlt-models](https://huggingface.co/ericleyu/openocr-mlt-models). It contains recognition graphs, shared weights, the character dictionary, the model manifest, and the PP-OCRv6 medium detector.
|
|
67
|
+
|
|
68
|
+
For offline use, copy the model archive to the target machine and import it locally:
|
|
69
|
+
|
|
70
|
+
~~~bash
|
|
71
|
+
python -m openocr_mlt fetch-models \
|
|
72
|
+
--source ./scriptmoe-medium-fp32-20261101-v1.tar.gz \
|
|
73
|
+
--cache-dir ./models --offline
|
|
74
|
+
~~~
|
|
75
|
+
|
|
76
|
+
The default cache location is $XDG_CACHE_HOME/openocr-mlt or ~/.cache/openocr-mlt. Download the [model archive](https://huggingface.co/ericleyu/openocr-mlt-models/resolve/7ef39160a893fc7e605e146c1544ba64c1a57f43/scriptmoe-medium-fp32-20261101-v1.tar.gz) on a machine with access to Hugging Face and transfer it to the target machine when necessary. Offline package installation also requires local copies of the Python dependencies.
|
|
77
|
+
|
|
78
|
+
## Python API
|
|
79
|
+
|
|
80
|
+
~~~python
|
|
81
|
+
from openocr_mlt import OpenOCRMLT, fetch_models
|
|
82
|
+
|
|
83
|
+
models = fetch_models(cache_dir="./models")
|
|
84
|
+
|
|
85
|
+
with OpenOCRMLT(
|
|
86
|
+
model_dir=models["recognition_dir"],
|
|
87
|
+
det_model_dir=models["detector_dir"],
|
|
88
|
+
device="cpu",
|
|
89
|
+
) as ocr:
|
|
90
|
+
result = ocr.ocr("./example.png")
|
|
91
|
+
print(result.to_dict())
|
|
92
|
+
~~~
|
|
93
|
+
|
|
94
|
+
Replace ./example.png with an existing image. Set device="cuda:0" in the CUDA environment to run detection and recognition on CUDA. The det_device and rec_device parameters select the two devices independently.
|
|
95
|
+
|
|
96
|
+
For cropped text recognition, initialize OpenOCRMLT with model_dir and call recognize(image). Results include the raw and filtered text, confidence score, status, decoding termination, and device information.
|
|
97
|
+
|
|
98
|
+
## Command Line
|
|
99
|
+
|
|
100
|
+
Whole-page OCR:
|
|
101
|
+
|
|
102
|
+
~~~bash
|
|
103
|
+
python -m openocr_mlt ocr ./example.png \
|
|
104
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
105
|
+
--det-model-dir ./models/scriptmoe-medium-fp32-20261101-v1/ppocrv6-medium-det-bce-v1 \
|
|
106
|
+
--device cpu
|
|
107
|
+
~~~
|
|
108
|
+
|
|
109
|
+
Cropped text recognition:
|
|
110
|
+
|
|
111
|
+
~~~bash
|
|
112
|
+
python -m openocr_mlt recognize ./crop.png \
|
|
113
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
114
|
+
--device cpu
|
|
115
|
+
~~~
|
|
116
|
+
|
|
117
|
+
Replace the image arguments with existing files. Run python -m openocr_mlt --help for all commands.
|
|
118
|
+
|
|
119
|
+
## Configuration
|
|
120
|
+
|
|
121
|
+
| Setting | Default |
|
|
122
|
+
|---|---|
|
|
123
|
+
| Precision | FP32 |
|
|
124
|
+
| Effective batch size | 1; images are processed serially |
|
|
125
|
+
| Maximum recognition length | 100 decoding steps |
|
|
126
|
+
| Maximum input ratio | 20 |
|
|
127
|
+
| Recognition confidence threshold | 0.5 |
|
|
128
|
+
| Maximum page side | 0, resizing disabled |
|
|
129
|
+
|
|
130
|
+
The evaluation configuration uses recognition threshold 0.7 and maximum page side 2,000 pixels. Set rec_threshold=0.7 and page_max_side=2000 in the API, or pass --rec-threshold 0.7 --page-max-side 2000 to the OCR command.
|
|
131
|
+
|
|
132
|
+
## Model Evaluation
|
|
133
|
+
|
|
134
|
+
The FP32 graphs were evaluated with openocr-mlt 0.3.0.dev14. The model bundle is unchanged.
|
|
135
|
+
|
|
136
|
+
| Task | Data | Result |
|
|
137
|
+
|---|---|---|
|
|
138
|
+
| CUDA recognition | TextMuSS, 10,899 crops | Official normalized weighted accuracy 85.0812%; ten-group macro accuracy 81.0928% |
|
|
139
|
+
| 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% |
|
|
140
|
+
|
|
141
|
+
Deployment validation 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.
|
|
142
|
+
|
|
143
|
+
## Sources
|
|
144
|
+
|
|
145
|
+
- [ScriptMoE](https://github.com/YesianRohn/ScriptMoE): multilingual recognition model and decoding design.
|
|
146
|
+
- [ppocrv6_onnx](https://github.com/AIwork4me/ppocrv6_onnx): detection preprocessing and postprocessing reference.
|
|
147
|
+
- PP-OCRv6 medium: detector distributed through Paddle's official model storage.
|
|
148
|
+
|
|
149
|
+
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,120 @@
|
|
|
1
|
+
# openocr-mlt
|
|
2
|
+
|
|
3
|
+
Multilingual OCR with ScriptMoE recognition and PP-OCRv6 medium text detection. The package provides cropped text recognition, whole-page OCR, a Python API, and a command-line interface.
|
|
4
|
+
|
|
5
|
+
Both models run with ONNX Runtime. Recognition uses autoregressive Prefill/Decode and KV caching. CPU and CUDA installations use separate runtime dependencies.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Use Linux x86_64 with Python 3.10.12 for the verified installation path. Select the CPU or CUDA extra in a virtual environment.
|
|
10
|
+
|
|
11
|
+
~~~bash
|
|
12
|
+
python3.10 -m venv .venv-cpu
|
|
13
|
+
.venv-cpu/bin/python -m pip install "openocr-mlt[cpu]"
|
|
14
|
+
~~~
|
|
15
|
+
|
|
16
|
+
For CUDA, use a separate environment:
|
|
17
|
+
|
|
18
|
+
~~~bash
|
|
19
|
+
python3.10 -m venv .venv-cuda
|
|
20
|
+
.venv-cuda/bin/python -m pip install "openocr-mlt[cuda]"
|
|
21
|
+
~~~
|
|
22
|
+
|
|
23
|
+
The CPU extra installs ONNX Runtime; the CUDA extra installs ONNX Runtime GPU and the required CUDA 12/cuDNN 9 user-space libraries. CUDA requires an NVIDIA driver. PyTorch is not required for ONNX inference. Install the CPU and CUDA extras in separate environments.
|
|
24
|
+
|
|
25
|
+
## Model Preparation
|
|
26
|
+
|
|
27
|
+
Activate the environment you installed, for example `source .venv-cpu/bin/activate`.
|
|
28
|
+
|
|
29
|
+
Download and verify the registered model bundle:
|
|
30
|
+
|
|
31
|
+
~~~bash
|
|
32
|
+
python -m openocr_mlt fetch-models --cache-dir ./models
|
|
33
|
+
~~~
|
|
34
|
+
|
|
35
|
+
Activate the selected virtual environment before running these commands. The command downloads the pinned FP32 bundle, verifies the archive and 40 model files, and returns the recognition and detector directories. Subsequent calls verify and reuse the cache.
|
|
36
|
+
|
|
37
|
+
The bundle is 213,794,128 bytes and is hosted in [ericleyu/openocr-mlt-models](https://huggingface.co/ericleyu/openocr-mlt-models). It contains recognition graphs, shared weights, the character dictionary, the model manifest, and the PP-OCRv6 medium detector.
|
|
38
|
+
|
|
39
|
+
For offline use, copy the model archive to the target machine and import it locally:
|
|
40
|
+
|
|
41
|
+
~~~bash
|
|
42
|
+
python -m openocr_mlt fetch-models \
|
|
43
|
+
--source ./scriptmoe-medium-fp32-20261101-v1.tar.gz \
|
|
44
|
+
--cache-dir ./models --offline
|
|
45
|
+
~~~
|
|
46
|
+
|
|
47
|
+
The default cache location is $XDG_CACHE_HOME/openocr-mlt or ~/.cache/openocr-mlt. Download the [model archive](https://huggingface.co/ericleyu/openocr-mlt-models/resolve/7ef39160a893fc7e605e146c1544ba64c1a57f43/scriptmoe-medium-fp32-20261101-v1.tar.gz) on a machine with access to Hugging Face and transfer it to the target machine when necessary. Offline package installation also requires local copies of the Python dependencies.
|
|
48
|
+
|
|
49
|
+
## Python API
|
|
50
|
+
|
|
51
|
+
~~~python
|
|
52
|
+
from openocr_mlt import OpenOCRMLT, fetch_models
|
|
53
|
+
|
|
54
|
+
models = fetch_models(cache_dir="./models")
|
|
55
|
+
|
|
56
|
+
with OpenOCRMLT(
|
|
57
|
+
model_dir=models["recognition_dir"],
|
|
58
|
+
det_model_dir=models["detector_dir"],
|
|
59
|
+
device="cpu",
|
|
60
|
+
) as ocr:
|
|
61
|
+
result = ocr.ocr("./example.png")
|
|
62
|
+
print(result.to_dict())
|
|
63
|
+
~~~
|
|
64
|
+
|
|
65
|
+
Replace ./example.png with an existing image. Set device="cuda:0" in the CUDA environment to run detection and recognition on CUDA. The det_device and rec_device parameters select the two devices independently.
|
|
66
|
+
|
|
67
|
+
For cropped text recognition, initialize OpenOCRMLT with model_dir and call recognize(image). Results include the raw and filtered text, confidence score, status, decoding termination, and device information.
|
|
68
|
+
|
|
69
|
+
## Command Line
|
|
70
|
+
|
|
71
|
+
Whole-page OCR:
|
|
72
|
+
|
|
73
|
+
~~~bash
|
|
74
|
+
python -m openocr_mlt ocr ./example.png \
|
|
75
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
76
|
+
--det-model-dir ./models/scriptmoe-medium-fp32-20261101-v1/ppocrv6-medium-det-bce-v1 \
|
|
77
|
+
--device cpu
|
|
78
|
+
~~~
|
|
79
|
+
|
|
80
|
+
Cropped text recognition:
|
|
81
|
+
|
|
82
|
+
~~~bash
|
|
83
|
+
python -m openocr_mlt recognize ./crop.png \
|
|
84
|
+
--model-dir ./models/scriptmoe-medium-fp32-20261101-v1/recognition \
|
|
85
|
+
--device cpu
|
|
86
|
+
~~~
|
|
87
|
+
|
|
88
|
+
Replace the image arguments with existing files. Run python -m openocr_mlt --help for all commands.
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
| Setting | Default |
|
|
93
|
+
|---|---|
|
|
94
|
+
| Precision | FP32 |
|
|
95
|
+
| Effective batch size | 1; images are processed serially |
|
|
96
|
+
| Maximum recognition length | 100 decoding steps |
|
|
97
|
+
| Maximum input ratio | 20 |
|
|
98
|
+
| Recognition confidence threshold | 0.5 |
|
|
99
|
+
| Maximum page side | 0, resizing disabled |
|
|
100
|
+
|
|
101
|
+
The evaluation configuration uses recognition threshold 0.7 and maximum page side 2,000 pixels. Set rec_threshold=0.7 and page_max_side=2000 in the API, or pass --rec-threshold 0.7 --page-max-side 2000 to the OCR command.
|
|
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
|
+
Deployment validation 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,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,9 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
See the [installation instructions](../README.md#installation) for Python and device requirements. Choose the CPU or CUDA extra and use a separate virtual environment for each device.
|
|
4
|
+
|
|
5
|
+
For installation from a release wheel, replace the package name with the local path:
|
|
6
|
+
|
|
7
|
+
`python -m pip install './openocr_mlt-0.3.0-py3-none-any.whl[cpu]'`
|
|
8
|
+
|
|
9
|
+
For offline installation, supply a local wheel directory with all matching dependencies and add `--no-index --find-links ./wheelhouse`. The [model preparation instructions](MODELS.md) cover the separate model archive.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Model Preparation
|
|
2
|
+
|
|
3
|
+
Use `openocr-mlt fetch-models` to download and verify the registered archive from its [pinned model repository revision](https://huggingface.co/ericleyu/openocr-mlt-models/resolve/7ef39160a893fc7e605e146c1544ba64c1a57f43/scriptmoe-medium-fp32-20261101-v1.tar.gz). The archive is 213,794,128 bytes with SHA256 `ee43e7358066ddf1286f61983024dc407808e350b1dd57eb986523eaf9417ad3`.
|
|
4
|
+
|
|
5
|
+
Use `openocr-mlt fetch-models --source ./scriptmoe-medium-fp32-20261101-v1.tar.gz --offline` to import a local copy. By default, the model cache is under `$XDG_CACHE_HOME/openocr-mlt` or `~/.cache/openocr-mlt`. The command returns the recognition and detector paths and checks all 40 files. See the [usage guide](../README.md#model-preparation) and [source notices](../THIRD_PARTY_NOTICES.md).
|
|
@@ -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))
|