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.
Files changed (57) hide show
  1. openocr_mlt_cuda-0.4.0/MANIFEST.in +7 -0
  2. openocr_mlt_cuda-0.4.0/PKG-INFO +120 -0
  3. openocr_mlt_cuda-0.4.0/README.md +94 -0
  4. openocr_mlt_cuda-0.4.0/THIRD_PARTY_NOTICES.md +26 -0
  5. openocr_mlt_cuda-0.4.0/docs/INSTALL.md +3 -0
  6. openocr_mlt_cuda-0.4.0/docs/MODELS.md +3 -0
  7. openocr_mlt_cuda-0.4.0/docs/VALIDATION.md +5 -0
  8. openocr_mlt_cuda-0.4.0/docs/verification/acceptance-summary.json +48 -0
  9. openocr_mlt_cuda-0.4.0/docs/verification/fp32-v14-summary.json +268 -0
  10. openocr_mlt_cuda-0.4.0/examples/demo-crop.png +0 -0
  11. openocr_mlt_cuda-0.4.0/examples/demo-page.png +0 -0
  12. openocr_mlt_cuda-0.4.0/examples/ocr_page.py +9 -0
  13. openocr_mlt_cuda-0.4.0/examples/prepared_ocr.py +13 -0
  14. openocr_mlt_cuda-0.4.0/examples/recognize.py +8 -0
  15. openocr_mlt_cuda-0.4.0/pyproject.toml +29 -0
  16. openocr_mlt_cuda-0.4.0/setup.cfg +4 -0
  17. openocr_mlt_cuda-0.4.0/src/openocr_mlt/__init__.py +11 -0
  18. openocr_mlt_cuda-0.4.0/src/openocr_mlt/__main__.py +2 -0
  19. openocr_mlt_cuda-0.4.0/src/openocr_mlt/api.py +275 -0
  20. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/THIRD_PARTY_NOTICES.txt +26 -0
  21. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/detector-models.json +37 -0
  22. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/dict.txt +19683 -0
  23. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/manifest.json +21 -0
  24. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/model-bundle.json +175 -0
  25. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/onnx-model.json +1565 -0
  26. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets/ppocrv6_onnx-LICENSE.txt +21 -0
  27. openocr_mlt_cuda-0.4.0/src/openocr_mlt/assets.py +37 -0
  28. openocr_mlt_cuda-0.4.0/src/openocr_mlt/cli.py +59 -0
  29. openocr_mlt_cuda-0.4.0/src/openocr_mlt/config.py +45 -0
  30. openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/__init__.py +4 -0
  31. openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/config.py +34 -0
  32. openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/cuda_runtime.py +44 -0
  33. openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/db.py +268 -0
  34. openocr_mlt_cuda-0.4.0/src/openocr_mlt/detection/onnx_backend.py +85 -0
  35. openocr_mlt_cuda-0.4.0/src/openocr_mlt/geometry.py +37 -0
  36. openocr_mlt_cuda-0.4.0/src/openocr_mlt/model_assets.py +34 -0
  37. openocr_mlt_cuda-0.4.0/src/openocr_mlt/model_fetch.py +166 -0
  38. openocr_mlt_cuda-0.4.0/src/openocr_mlt/onnx_runtime.py +87 -0
  39. openocr_mlt_cuda-0.4.0/src/openocr_mlt/processing.py +82 -0
  40. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/__init__.py +1 -0
  41. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/cuda_stream.py +39 -0
  42. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/modeling.py +777 -0
  43. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/onnx_backend.py +100 -0
  44. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/partitioned_prefill.py +67 -0
  45. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/postprocess.py +87 -0
  46. openocr_mlt_cuda-0.4.0/src/openocr_mlt/recognition/torch_backend.py +31 -0
  47. openocr_mlt_cuda-0.4.0/src/openocr_mlt/types.py +71 -0
  48. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/PKG-INFO +120 -0
  49. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/SOURCES.txt +56 -0
  50. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/dependency_links.txt +1 -0
  51. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/entry_points.txt +2 -0
  52. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/requires.txt +16 -0
  53. openocr_mlt_cuda-0.4.0/src/openocr_mlt_cuda.egg-info/top_level.txt +1 -0
  54. openocr_mlt_cuda-0.4.0/tools/export_scriptmoe.py +120 -0
  55. openocr_mlt_cuda-0.4.0/tools/prepare_decode_views.py +44 -0
  56. openocr_mlt_cuda-0.4.0/tools/prepare_onnx_models.py +4 -0
  57. openocr_mlt_cuda-0.4.0/tools/prepare_prefill_pipeline.py +79 -0
@@ -0,0 +1,7 @@
1
+ include README.md THIRD_PARTY_NOTICES.md
2
+ recursive-include examples *.py *.png
3
+ recursive-include tools *.py
4
+ recursive-include constraints *.txt *.lock
5
+ prune tests
6
+ recursive-include docs *.md
7
+ recursive-include docs *.json
@@ -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,3 @@
1
+ # Installation
2
+
3
+ See the [installation and usage guide](../README.md#installation) for separate CPU and CUDA installations, Python requirements, and runtime selection.
@@ -0,0 +1,3 @@
1
+ # Model preparation
2
+
3
+ See the [model preparation guide](../README.md#model-preparation) for first-use download, the verified model cache, and offline import.
@@ -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
+ }
@@ -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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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")