onnxtr 0.3.2__py3-none-any.whl → 0.4.1__py3-none-any.whl

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.
onnxtr/models/__init__.py CHANGED
@@ -3,3 +3,4 @@ from .classification import *
3
3
  from .detection import *
4
4
  from .recognition import *
5
5
  from .zoo import *
6
+ from .factory import *
@@ -56,6 +56,7 @@ class MobileNetV3(Engine):
56
56
  **kwargs: Any,
57
57
  ) -> None:
58
58
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
59
+
59
60
  self.cfg = cfg
60
61
 
61
62
  def __call__(
@@ -64,8 +64,10 @@ class DBNet(Engine):
64
64
  **kwargs: Any,
65
65
  ) -> None:
66
66
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
67
+
67
68
  self.cfg = cfg
68
69
  self.assume_straight_pages = assume_straight_pages
70
+
69
71
  self.postprocessor = GeneralDetectionPostProcessor(
70
72
  assume_straight_pages=self.assume_straight_pages, bin_thresh=bin_thresh, box_thresh=box_thresh
71
73
  )
@@ -62,6 +62,7 @@ class FAST(Engine):
62
62
  **kwargs: Any,
63
63
  ) -> None:
64
64
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
65
+
65
66
  self.cfg = cfg
66
67
  self.assume_straight_pages = assume_straight_pages
67
68
 
@@ -64,6 +64,7 @@ class LinkNet(Engine):
64
64
  **kwargs: Any,
65
65
  ) -> None:
66
66
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
67
+
67
68
  self.cfg = cfg
68
69
  self.assume_straight_pages = assume_straight_pages
69
70
 
onnxtr/models/engine.py CHANGED
@@ -90,6 +90,8 @@ class Engine:
90
90
  def __init__(self, url: str, engine_cfg: Optional[EngineConfig] = None, **kwargs: Any) -> None:
91
91
  engine_cfg = engine_cfg if isinstance(engine_cfg, EngineConfig) else EngineConfig()
92
92
  archive_path = download_from_url(url, cache_subdir="models", **kwargs) if "http" in url else url
93
+ # Store model path for each model
94
+ self.model_path = archive_path
93
95
  self.session_options = engine_cfg.session_options
94
96
  self.providers = engine_cfg.providers
95
97
  self.runtime = InferenceSession(archive_path, providers=self.providers, sess_options=self.session_options)
@@ -0,0 +1 @@
1
+ from .hub import *
@@ -0,0 +1,224 @@
1
+ # Copyright (C) 2021-2024, Mindee | Felix Dittrich.
2
+
3
+ # This program is licensed under the Apache License 2.0.
4
+ # See LICENSE or go to <https://opensource.org/licenses/Apache-2.0> for full license details.
5
+
6
+ # Inspired by: https://github.com/rwightman/pytorch-image-models/blob/master/timm/models/hub.py
7
+
8
+ import json
9
+ import logging
10
+ import os
11
+ import shutil
12
+ import subprocess
13
+ import textwrap
14
+ from pathlib import Path
15
+ from typing import Any, Optional
16
+
17
+ from huggingface_hub import (
18
+ HfApi,
19
+ Repository,
20
+ get_token,
21
+ get_token_permission,
22
+ hf_hub_download,
23
+ login,
24
+ )
25
+
26
+ from onnxtr import models
27
+ from onnxtr.models.engine import EngineConfig
28
+
29
+ __all__ = ["login_to_hub", "push_to_hf_hub", "from_hub", "_save_model_and_config_for_hf_hub"]
30
+
31
+
32
+ AVAILABLE_ARCHS = {
33
+ "classification": models.classification.zoo.ORIENTATION_ARCHS,
34
+ "detection": models.detection.zoo.ARCHS,
35
+ "recognition": models.recognition.zoo.ARCHS,
36
+ }
37
+
38
+
39
+ def login_to_hub() -> None: # pragma: no cover
40
+ """Login to huggingface hub"""
41
+ access_token = get_token()
42
+ if access_token is not None and get_token_permission(access_token):
43
+ logging.info("Huggingface Hub token found and valid")
44
+ login(token=access_token, write_permission=True)
45
+ else:
46
+ login()
47
+ # check if git lfs is installed
48
+ try:
49
+ subprocess.call(["git", "lfs", "version"])
50
+ except FileNotFoundError:
51
+ raise OSError(
52
+ "Looks like you do not have git-lfs installed, please install. \
53
+ You can install from https://git-lfs.github.com/. \
54
+ Then run `git lfs install` (you only have to do this once)."
55
+ )
56
+
57
+
58
+ def _save_model_and_config_for_hf_hub(model: Any, save_dir: str, arch: str, task: str) -> None:
59
+ """Save model and config to disk for pushing to huggingface hub
60
+
61
+ Args:
62
+ ----
63
+ model: Onnx model to be saved
64
+ save_dir: directory to save model and config
65
+ arch: architecture name
66
+ task: task name
67
+ """
68
+ save_directory = Path(save_dir)
69
+ shutil.copy2(model.model_path, save_directory / "model.onnx")
70
+
71
+ config_path = save_directory / "config.json"
72
+
73
+ # add model configuration
74
+ model_config = model.cfg
75
+ model_config["arch"] = arch
76
+ model_config["task"] = task
77
+
78
+ with config_path.open("w") as f:
79
+ json.dump(model_config, f, indent=2, ensure_ascii=False)
80
+
81
+
82
+ def push_to_hf_hub(
83
+ model: Any, model_name: str, task: str, override: bool = False, **kwargs
84
+ ) -> None: # pragma: no cover
85
+ """Save model and its configuration on HF hub
86
+
87
+ >>> from onnxtr.models import login_to_hub, push_to_hf_hub
88
+ >>> from onnxtr.models.recognition import crnn_mobilenet_v3_small
89
+ >>> login_to_hub()
90
+ >>> model = crnn_mobilenet_v3_small()
91
+ >>> push_to_hf_hub(model, 'my-model', 'recognition', arch='crnn_mobilenet_v3_small')
92
+
93
+ Args:
94
+ ----
95
+ model: Onnx model to be saved
96
+ model_name: name of the model which is also the repository name
97
+ task: task name
98
+ override: whether to override the existing model / repo on HF hub
99
+ **kwargs: keyword arguments for push_to_hf_hub
100
+ """
101
+ run_config = kwargs.get("run_config", None)
102
+ arch = kwargs.get("arch", None)
103
+
104
+ if run_config is None and arch is None:
105
+ raise ValueError("run_config or arch must be specified")
106
+ if task not in ["classification", "detection", "recognition"]:
107
+ raise ValueError("task must be one of classification, detection, recognition")
108
+
109
+ # default readme
110
+ readme = textwrap.dedent(
111
+ f"""
112
+ ---
113
+ language:
114
+ - en
115
+ - fr
116
+ license: apache-2.0
117
+ ---
118
+
119
+ <p align="center">
120
+ <img src="https://github.com/felixdittrich92/OnnxTR/raw/main/docs/images/logo.jpg" width="40%">
121
+ </p>
122
+
123
+ **Optical Character Recognition made seamless & accessible to anyone, powered by Onnxruntime**
124
+
125
+ ## Task: {task}
126
+
127
+ https://github.com/felixdittrich92/OnnxTR
128
+
129
+ ### Example usage:
130
+
131
+ ```python
132
+ >>> from onnxtr.io import DocumentFile
133
+ >>> from onnxtr.models import ocr_predictor, from_hub
134
+
135
+ >>> img = DocumentFile.from_images(['<image_path>'])
136
+ >>> # Load your model from the hub
137
+ >>> model = from_hub('onnxtr/my-model')
138
+
139
+ >>> # Pass it to the predictor
140
+ >>> # If your model is a recognition model:
141
+ >>> predictor = ocr_predictor(det_arch='db_mobilenet_v3_large',
142
+ >>> reco_arch=model)
143
+
144
+ >>> # If your model is a detection model:
145
+ >>> predictor = ocr_predictor(det_arch=model,
146
+ >>> reco_arch='crnn_mobilenet_v3_small')
147
+
148
+ >>> # Get your predictions
149
+ >>> res = predictor(img)
150
+ ```
151
+ """
152
+ )
153
+
154
+ # add run configuration to readme if available
155
+ if run_config is not None:
156
+ arch = run_config.arch
157
+ readme += textwrap.dedent(
158
+ f"""### Run Configuration
159
+ \n{json.dumps(vars(run_config), indent=2, ensure_ascii=False)}"""
160
+ )
161
+
162
+ if arch not in AVAILABLE_ARCHS[task]:
163
+ raise ValueError(
164
+ f"Architecture: {arch} for task: {task} not found.\
165
+ \nAvailable architectures: {AVAILABLE_ARCHS}"
166
+ )
167
+
168
+ commit_message = f"Add {model_name} model"
169
+
170
+ local_cache_dir = os.path.join(os.path.expanduser("~"), ".cache", "huggingface", "hub", model_name)
171
+ repo_url = HfApi().create_repo(model_name, token=get_token(), exist_ok=override)
172
+ repo = Repository(local_dir=local_cache_dir, clone_from=repo_url)
173
+
174
+ with repo.commit(commit_message):
175
+ _save_model_and_config_for_hf_hub(model, repo.local_dir, arch=arch, task=task)
176
+ readme_path = Path(repo.local_dir) / "README.md"
177
+ readme_path.write_text(readme)
178
+
179
+ repo.git_push()
180
+
181
+
182
+ def from_hub(repo_id: str, engine_cfg: Optional[EngineConfig] = None, **kwargs: Any):
183
+ """Instantiate & load a pretrained model from HF hub.
184
+
185
+ >>> from onnxtr.models import from_hub
186
+ >>> model = from_hub("onnxtr/my-model")
187
+
188
+ Args:
189
+ ----
190
+ repo_id: HuggingFace model hub repo
191
+ engine_cfg: configuration for the inference engine (optional)
192
+ kwargs: kwargs of `hf_hub_download`
193
+
194
+ Returns:
195
+ -------
196
+ Model loaded with the checkpoint
197
+ """
198
+ # Get the config
199
+ with open(hf_hub_download(repo_id, filename="config.json", **kwargs), "rb") as f:
200
+ cfg = json.load(f)
201
+ model_path = hf_hub_download(repo_id, filename="model.onnx", **kwargs)
202
+
203
+ arch = cfg["arch"]
204
+ task = cfg["task"]
205
+ cfg.pop("arch")
206
+ cfg.pop("task")
207
+
208
+ if task == "classification":
209
+ model = models.classification.__dict__[arch](model_path, classes=cfg["classes"], engine_cfg=engine_cfg)
210
+ elif task == "detection":
211
+ model = models.detection.__dict__[arch](model_path, engine_cfg=engine_cfg)
212
+ elif task == "recognition":
213
+ model = models.recognition.__dict__[arch](
214
+ model_path, input_shape=cfg["input_shape"], vocab=cfg["vocab"], engine_cfg=engine_cfg
215
+ )
216
+
217
+ # convert all values which are lists to tuples
218
+ for key, value in cfg.items():
219
+ if isinstance(value, list):
220
+ cfg[key] = tuple(value)
221
+ # update model cfg
222
+ model.cfg = cfg
223
+
224
+ return model
@@ -112,8 +112,8 @@ class _OCRPredictor:
112
112
  ]
113
113
  )
114
114
  return [
115
- # We exapnd if the page is wider than tall and the angle is 90 or -90
116
- rotate_image(page, angle, expand=page.shape[1] > page.shape[0] and abs(angle) == 90)
115
+ # expand if height and width are not equal
116
+ rotate_image(page, angle, expand=page.shape[0] != page.shape[1])
117
117
  for page, angle in zip(pages, origin_pages_orientations)
118
118
  ]
119
119
 
@@ -100,6 +100,8 @@ class OCRPredictor(NestedObject, _OCRPredictor):
100
100
  origin_pages_orientations = None
101
101
  if self.straighten_pages:
102
102
  pages = self._straighten_pages(pages, seg_maps, general_pages_orientations, origin_pages_orientations)
103
+ # update page shapes after straightening
104
+ origin_page_shapes = [page.shape[:2] for page in pages]
103
105
 
104
106
  # forward again to get predictions on straight pages
105
107
  loc_preds = self.det_predictor(pages, **kwargs) # type: ignore[assignment]
@@ -129,8 +129,10 @@ class CRNN(Engine):
129
129
  **kwargs: Any,
130
130
  ) -> None:
131
131
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
132
+
132
133
  self.vocab = vocab
133
134
  self.cfg = cfg
135
+
134
136
  self.postprocessor = CRNNPostProcessor(self.vocab)
135
137
 
136
138
  def __call__(
@@ -53,6 +53,7 @@ class MASTER(Engine):
53
53
 
54
54
  self.vocab = vocab
55
55
  self.cfg = cfg
56
+
56
57
  self.postprocessor = MASTERPostProcessor(vocab=self.vocab)
57
58
 
58
59
  def __call__(
@@ -49,8 +49,10 @@ class PARSeq(Engine):
49
49
  **kwargs: Any,
50
50
  ) -> None:
51
51
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
52
+
52
53
  self.vocab = vocab
53
54
  self.cfg = cfg
55
+
54
56
  self.postprocessor = PARSeqPostProcessor(vocab=self.vocab)
55
57
 
56
58
  def __call__(
@@ -49,8 +49,10 @@ class SAR(Engine):
49
49
  **kwargs: Any,
50
50
  ) -> None:
51
51
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
52
+
52
53
  self.vocab = vocab
53
54
  self.cfg = cfg
55
+
54
56
  self.postprocessor = SARPostProcessor(self.vocab)
55
57
 
56
58
  def __call__(
@@ -57,6 +57,7 @@ class ViTSTR(Engine):
57
57
  **kwargs: Any,
58
58
  ) -> None:
59
59
  super().__init__(url=model_path, engine_cfg=engine_cfg, **kwargs)
60
+
60
61
  self.vocab = vocab
61
62
  self.cfg = cfg
62
63
 
onnxtr/utils/vocabs.py CHANGED
@@ -17,9 +17,14 @@ VOCABS: Dict[str, str] = {
17
17
  "ancient_greek": "αβγδεζηθικλμνξοπρστυφχψωΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩ",
18
18
  "arabic_letters": "ءآأؤإئابةتثجحخدذرزسشصضطظعغـفقكلمنهوىي",
19
19
  "persian_letters": "پچڢڤگ",
20
- "hindi_digits": "٠١٢٣٤٥٦٧٨٩",
20
+ "arabic_digits": "٠١٢٣٤٥٦٧٨٩",
21
21
  "arabic_diacritics": "ًٌٍَُِّْ",
22
22
  "arabic_punctuation": "؟؛«»—",
23
+ "hindi_letters": "अआइईउऊऋॠऌॡएऐओऔअंअःकखगघङचछजझञटठडढणतथदधनपफबभमयरलवशषसह",
24
+ "hindi_digits": "०१२३४५६७८९",
25
+ "hindi_punctuation": "।,?!:्ॐ॰॥॰",
26
+ "bangla_letters": "অআইঈউঊঋএঐওঔকখগঘঙচছজঝঞটঠডঢণতথদধনপফবভমযরলশষসহ়ঽািীুূৃেৈোৌ্ৎংঃঁ",
27
+ "bangla_digits": "০১২৩৪৫৬৭৮৯",
23
28
  }
24
29
 
25
30
  VOCABS["latin"] = VOCABS["digits"] + VOCABS["ascii_letters"] + VOCABS["punctuation"]
@@ -32,7 +37,7 @@ VOCABS["italian"] = VOCABS["english"] + "àèéìíîòóùúÀÈÉÌÍÎÒÓÙ
32
37
  VOCABS["german"] = VOCABS["english"] + "äöüßÄÖÜẞ"
33
38
  VOCABS["arabic"] = (
34
39
  VOCABS["digits"]
35
- + VOCABS["hindi_digits"]
40
+ + VOCABS["arabic_digits"]
36
41
  + VOCABS["arabic_letters"]
37
42
  + VOCABS["persian_letters"]
38
43
  + VOCABS["arabic_diacritics"]
@@ -48,10 +53,12 @@ VOCABS["finnish"] = VOCABS["english"] + "äöÄÖ"
48
53
  VOCABS["swedish"] = VOCABS["english"] + "åäöÅÄÖ"
49
54
  VOCABS["vietnamese"] = (
50
55
  VOCABS["english"]
51
- + "áàảạãăắằẳẵặâấầẩẫậéèẻẽẹêếềểễệóòỏõọôốồổộỗơớờởợỡúùủũụưứừửữựiíìỉĩịýỳỷỹỵ"
52
- + "ÁÀẢẠÃĂẮẰẲẴẶÂẤẦẨẪẬÉÈẺẼẸÊẾỀỂỄỆÓÒỎÕỌÔỐỒỔỘỖƠỚỜỞỢỠÚÙỦŨỤƯỨỪỬỮỰIÍÌỈĨỊÝỲỶỸỴ"
56
+ + "áàảạãăắằẳẵặâấầẩẫậđéèẻẽẹêếềểễệóòỏõọôốồổộỗơớờởợỡúùủũụưứừửữựiíìỉĩịýỳỷỹỵ"
57
+ + "ÁÀẢẠÃĂẮẰẲẴẶÂẤẦẨẪẬĐÉÈẺẼẸÊẾỀỂỄỆÓÒỎÕỌÔỐỒỔỘỖƠỚỜỞỢỠÚÙỦŨỤƯỨỪỬỮỰIÍÌỈĨỊÝỲỶỸỴ"
53
58
  )
54
59
  VOCABS["hebrew"] = VOCABS["english"] + "אבגדהוזחטיכלמנסעפצקרשת" + "₪"
60
+ VOCABS["hindi"] = VOCABS["hindi_letters"] + VOCABS["hindi_digits"] + VOCABS["hindi_punctuation"]
61
+ VOCABS["bangla"] = VOCABS["bangla_letters"] + VOCABS["bangla_digits"]
55
62
  VOCABS["multilingual"] = "".join(
56
63
  dict.fromkeys(
57
64
  VOCABS["french"]
onnxtr/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = 'v0.3.2'
1
+ __version__ = 'v0.4.1'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: onnxtr
3
- Version: 0.3.2
3
+ Version: 0.4.1
4
4
  Summary: Onnx Text Recognition (OnnxTR): docTR Onnx-Wrapper for high-performance OCR on documents.
5
5
  Author-email: Felix Dittrich <felixdittrich92@gmail.com>
6
6
  Maintainer: Felix Dittrich
@@ -225,46 +225,47 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
225
225
  Requires-Python: <4,>=3.9.0
226
226
  Description-Content-Type: text/markdown
227
227
  License-File: LICENSE
228
- Requires-Dist: numpy <2.0.0,>=1.16.0
229
- Requires-Dist: scipy <2.0.0,>=1.4.0
230
- Requires-Dist: opencv-python <5.0.0,>=4.5.0
231
- Requires-Dist: pypdfium2 <5.0.0,>=4.11.0
232
- Requires-Dist: pyclipper <2.0.0,>=1.2.0
233
- Requires-Dist: shapely <3.0.0,>=1.6.0
234
- Requires-Dist: rapidfuzz <4.0.0,>=3.0.0
235
- Requires-Dist: langdetect <2.0.0,>=1.0.9
236
- Requires-Dist: Pillow >=9.2.0
237
- Requires-Dist: defusedxml >=0.7.0
238
- Requires-Dist: anyascii >=0.3.2
239
- Requires-Dist: tqdm >=4.30.0
228
+ Requires-Dist: numpy<3.0.0,>=1.16.0
229
+ Requires-Dist: scipy<2.0.0,>=1.4.0
230
+ Requires-Dist: opencv-python<5.0.0,>=4.5.0
231
+ Requires-Dist: pypdfium2<5.0.0,>=4.11.0
232
+ Requires-Dist: pyclipper<2.0.0,>=1.2.0
233
+ Requires-Dist: shapely<3.0.0,>=1.6.0
234
+ Requires-Dist: rapidfuzz<4.0.0,>=3.0.0
235
+ Requires-Dist: langdetect<2.0.0,>=1.0.9
236
+ Requires-Dist: huggingface-hub<1.0.0,>=0.23.0
237
+ Requires-Dist: Pillow>=9.2.0
238
+ Requires-Dist: defusedxml>=0.7.0
239
+ Requires-Dist: anyascii>=0.3.2
240
+ Requires-Dist: tqdm>=4.30.0
240
241
  Provides-Extra: cpu
241
- Requires-Dist: onnxruntime >=1.11.0 ; extra == 'cpu'
242
+ Requires-Dist: onnxruntime>=1.11.0; extra == "cpu"
242
243
  Provides-Extra: dev
243
- Requires-Dist: onnxruntime >=1.11.0 ; extra == 'dev'
244
- Requires-Dist: weasyprint >=55.0 ; extra == 'dev'
245
- Requires-Dist: matplotlib >=3.1.0 ; extra == 'dev'
246
- Requires-Dist: mplcursors >=0.3 ; extra == 'dev'
247
- Requires-Dist: pytest >=5.3.2 ; extra == 'dev'
248
- Requires-Dist: coverage[toml] >=4.5.4 ; extra == 'dev'
249
- Requires-Dist: requests >=2.20.0 ; extra == 'dev'
250
- Requires-Dist: ruff >=0.1.5 ; extra == 'dev'
251
- Requires-Dist: mypy >=0.812 ; extra == 'dev'
252
- Requires-Dist: pre-commit >=2.17.0 ; extra == 'dev'
244
+ Requires-Dist: onnxruntime>=1.11.0; extra == "dev"
245
+ Requires-Dist: weasyprint>=55.0; extra == "dev"
246
+ Requires-Dist: matplotlib>=3.1.0; extra == "dev"
247
+ Requires-Dist: mplcursors>=0.3; extra == "dev"
248
+ Requires-Dist: pytest>=5.3.2; extra == "dev"
249
+ Requires-Dist: coverage[toml]>=4.5.4; extra == "dev"
250
+ Requires-Dist: requests>=2.20.0; extra == "dev"
251
+ Requires-Dist: ruff>=0.1.5; extra == "dev"
252
+ Requires-Dist: mypy>=0.812; extra == "dev"
253
+ Requires-Dist: pre-commit>=2.17.0; extra == "dev"
253
254
  Provides-Extra: gpu
254
- Requires-Dist: onnxruntime-gpu >=1.11.0 ; extra == 'gpu'
255
+ Requires-Dist: onnxruntime-gpu>=1.11.0; extra == "gpu"
255
256
  Provides-Extra: html
256
- Requires-Dist: weasyprint >=55.0 ; extra == 'html'
257
+ Requires-Dist: weasyprint>=55.0; extra == "html"
257
258
  Provides-Extra: quality
258
- Requires-Dist: ruff >=0.1.5 ; extra == 'quality'
259
- Requires-Dist: mypy >=0.812 ; extra == 'quality'
260
- Requires-Dist: pre-commit >=2.17.0 ; extra == 'quality'
259
+ Requires-Dist: ruff>=0.1.5; extra == "quality"
260
+ Requires-Dist: mypy>=0.812; extra == "quality"
261
+ Requires-Dist: pre-commit>=2.17.0; extra == "quality"
261
262
  Provides-Extra: testing
262
- Requires-Dist: pytest >=5.3.2 ; extra == 'testing'
263
- Requires-Dist: coverage[toml] >=4.5.4 ; extra == 'testing'
264
- Requires-Dist: requests >=2.20.0 ; extra == 'testing'
263
+ Requires-Dist: pytest>=5.3.2; extra == "testing"
264
+ Requires-Dist: coverage[toml]>=4.5.4; extra == "testing"
265
+ Requires-Dist: requests>=2.20.0; extra == "testing"
265
266
  Provides-Extra: viz
266
- Requires-Dist: matplotlib >=3.1.0 ; extra == 'viz'
267
- Requires-Dist: mplcursors >=0.3 ; extra == 'viz'
267
+ Requires-Dist: matplotlib>=3.1.0; extra == "viz"
268
+ Requires-Dist: mplcursors>=0.3; extra == "viz"
268
269
 
269
270
  <p align="center">
270
271
  <img src="https://github.com/felixdittrich92/OnnxTR/raw/main/docs/images/logo.jpg" width="40%">
@@ -275,7 +276,7 @@ Requires-Dist: mplcursors >=0.3 ; extra == 'viz'
275
276
  [![codecov](https://codecov.io/gh/felixdittrich92/OnnxTR/graph/badge.svg?token=WVFRCQBOLI)](https://codecov.io/gh/felixdittrich92/OnnxTR)
276
277
  [![Codacy Badge](https://app.codacy.com/project/badge/Grade/4fff4d764bb14fb8b4f4afeb9587231b)](https://app.codacy.com/gh/felixdittrich92/OnnxTR/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
277
278
  [![CodeFactor](https://www.codefactor.io/repository/github/felixdittrich92/onnxtr/badge)](https://www.codefactor.io/repository/github/felixdittrich92/onnxtr)
278
- [![Pypi](https://img.shields.io/badge/pypi-v0.3.1-blue.svg)](https://pypi.org/project/OnnxTR/)
279
+ [![Pypi](https://img.shields.io/badge/pypi-v0.4.1-blue.svg)](https://pypi.org/project/OnnxTR/)
279
280
 
280
281
  > :warning: Please note that this is a wrapper around the [doctr](https://github.com/mindee/doctr) library to provide a Onnx pipeline for docTR. For feature requests, which are not directly related to the Onnx pipeline, please refer to the base project.
281
282
 
@@ -449,6 +450,69 @@ det_model = linknet_resnet18("path_to_custom_model.onnx")
449
450
  model = ocr_predictor(det_arch=det_model, reco_arch=reco_model)
450
451
  ```
451
452
 
453
+ ## Loading models from HuggingFace Hub
454
+
455
+ You can also load models from the HuggingFace Hub:
456
+
457
+ ```python
458
+ from onnxtr.io import DocumentFile
459
+ from onnxtr.models import ocr_predictor, from_hub
460
+
461
+ img = DocumentFile.from_images(['<image_path>'])
462
+ # Load your model from the hub
463
+ model = from_hub('onnxtr/my-model')
464
+
465
+ # Pass it to the predictor
466
+ # If your model is a recognition model:
467
+ predictor = ocr_predictor(
468
+ det_arch='db_mobilenet_v3_large',
469
+ reco_arch=model
470
+ )
471
+
472
+ # If your model is a detection model:
473
+ predictor = ocr_predictor(
474
+ det_arch=model,
475
+ reco_arch='crnn_mobilenet_v3_small'
476
+ )
477
+
478
+ # Get your predictions
479
+ res = predictor(img)
480
+ ```
481
+
482
+ HF Hub search: [here](https://huggingface.co/models?search=onnxtr).
483
+
484
+ Collection: [here](https://huggingface.co/collections/Felix92/onnxtr-66bf213a9f88f7346c90e842)
485
+
486
+ Or push your own models to the hub:
487
+
488
+ ```python
489
+ from onnxtr.models import parseq, push_to_hf_hub, login_to_hub
490
+ from onnxtr.utils.vocabs import VOCABS
491
+
492
+ # Login to the hub
493
+ login_to_hub()
494
+
495
+ # Recogniton model
496
+ model = parseq("~/onnxtr-parseq-multilingual-v1.onnx", vocab=VOCABS["multilingual"])
497
+ push_to_hf_hub(
498
+ model,
499
+ model_name="onnxtr-parseq-multilingual-v1",
500
+ task="recognition", # The task for which the model is intended [detection, recognition, classification]
501
+ arch="parseq", # The name of the model architecture
502
+ override=False # Set to `True` if you want to override an existing model / repository
503
+ )
504
+
505
+ # Detection model
506
+ model = linknet_resnet18("~/onnxtr-linknet-resnet18.onnx")
507
+ push_to_hf_hub(
508
+ model,
509
+ model_name="onnxtr-linknet-resnet18",
510
+ task="detection",
511
+ arch="linknet_resnet18",
512
+ override=True
513
+ )
514
+ ```
515
+
452
516
  ## Models architectures
453
517
 
454
518
  Credits where it's due: this repository provides ONNX models for the following architectures, converted from the docTR models:
@@ -525,8 +589,8 @@ The smallest combination in OnnxTR (docTR) of `db_mobilenet_v3_large` and `crnn_
525
589
  |Library |FUNSD (199 pages) |CORD (900 pages) |
526
590
  |---------------------------------|-------------------------------|-------------------------------|
527
591
  |docTR (CPU) - v0.8.1 | ~1.29s / Page | ~0.60s / Page |
528
- |**OnnxTR (CPU)** - v0.1.2 | ~0.57s / Page | **~0.25s / Page** |
529
- |**OnnxTR (CPU) 8-bit** - v0.1.2 | **~0.38s / Page** | **~0.14s / Page** |
592
+ |**OnnxTR (CPU)** - v0.4.1 | ~0.57s / Page | **~0.25s / Page** |
593
+ |**OnnxTR (CPU) 8-bit** - v0.4.1 | **~0.38s / Page** | **~0.14s / Page** |
530
594
  |EasyOCR (CPU) - v1.7.1 | ~1.96s / Page | ~1.75s / Page |
531
595
  |**PyTesseract (CPU)** - v0.3.10 | **~0.50s / Page** | ~0.52s / Page |
532
596
  |Surya (line) (CPU) - v0.4.4 | ~48.76s / Page | ~35.49s / Page |
@@ -538,7 +602,7 @@ The smallest combination in OnnxTR (docTR) of `db_mobilenet_v3_large` and `crnn_
538
602
  |-------------------------------------|-------------------------------|-------------------------------|
539
603
  |docTR (GPU) - v0.8.1 | ~0.07s / Page | ~0.05s / Page |
540
604
  |**docTR (GPU) float16** - v0.8.1 | **~0.06s / Page** | **~0.03s / Page** |
541
- |OnnxTR (GPU) - v0.1.2 | **~0.06s / Page** | ~0.04s / Page |
605
+ |OnnxTR (GPU) - v0.4.1 | **~0.06s / Page** | ~0.04s / Page |
542
606
  |EasyOCR (GPU) - v1.7.1 | ~0.31s / Page | ~0.19s / Page |
543
607
  |Surya (GPU) float16 - v0.4.4 | ~3.70s / Page | ~2.81s / Page |
544
608
  |**PaddleOCR (GPU) - no cls - v2.7.3**| ~0.08s / Page | **~0.03s / Page** |
@@ -557,6 +621,16 @@ If you wish to cite please refer to the base project citation, feel free to use
557
621
  }
558
622
  ```
559
623
 
624
+ ```bibtex
625
+ @misc{onnxtr2024,
626
+ title={OnnxTR: Optical Character Recognition made seamless & accessible to anyone, powered by Onnx},
627
+ author={Felix Dittrich},
628
+ year={2024},
629
+ publisher = {GitHub},
630
+ howpublished = {\url{https://github.com/felixdittrich92/OnnxTR}}
631
+ }
632
+ ```
633
+
560
634
  ## License
561
635
 
562
636
  Distributed under the Apache 2.0 License. See [`LICENSE`](https://github.com/felixdittrich92/OnnxTR?tab=Apache-2.0-1-ov-file#readme) for more information.
@@ -1,7 +1,7 @@
1
1
  onnxtr/__init__.py,sha256=h7Wc2tuHLsaoCk5xNpEFEK-g11A6SJA7nAasA76TQ_Y,100
2
2
  onnxtr/file_utils.py,sha256=WjUKalEdR53aoeIY4e-ihy3r7J_C9qFxL40JHGPfutc,1107
3
3
  onnxtr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- onnxtr/version.py,sha256=Mqv-IS8XNTfhjRfomiPmqTyHtOUKl9tLeE2KEmYIkeM,23
4
+ onnxtr/version.py,sha256=FMLDI1-41V4TL8AtTJYDQPs1_pJ9uac4WXnI9j16CjY,23
5
5
  onnxtr/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  onnxtr/contrib/artefacts.py,sha256=tdmfhvfXVRYEH7uj4_hqf2cuUGoTieyNK8bXsD3zHwo,5383
7
7
  onnxtr/contrib/base.py,sha256=KyJ8_zDSKEWSFBszgCbLjEeI7SKg4N_iH_ZQNf90SWQ,3288
@@ -11,15 +11,15 @@ onnxtr/io/html.py,sha256=Em_7PjZ56SugJ9bjjcWLCMVe5ee6uUMKeZovNxJFAXw,737
11
11
  onnxtr/io/image.py,sha256=4tLTh2bGdA0ohh3a6mV6xD0KqNOtIVi5lJ06XSmeyMI,1759
12
12
  onnxtr/io/pdf.py,sha256=tD0klmxI-gkMXp56f_ZXWyPHLsUBKa_xlhNTtGV6tpU,1367
13
13
  onnxtr/io/reader.py,sha256=BA7DPhW-Gkmce_ZfzrOl4H3pSXVy2JBeQEuY3pWrBFg,2852
14
- onnxtr/models/__init__.py,sha256=Rg-5P2e622q-5ScfxVE3G8GXa51HUPS7b0jkvdukFzM,134
14
+ onnxtr/models/__init__.py,sha256=QTfZlqUyv1d7NUCbGIUFM1DLOOXe-cqHZ7uaKkGdXvk,157
15
15
  onnxtr/models/_utils.py,sha256=KncsNcoWqbsxFwduce2STuGHLhv63nXEHv7CMuh6wYA,6606
16
16
  onnxtr/models/builder.py,sha256=Bzg-XHZc5k16Ti2XeV9hm4POTHofe581Azq1a3d1O6E,14296
17
- onnxtr/models/engine.py,sha256=fPpQzX_wNoxkPcECbGHFoIYtphHVQD9YkJG9hXFu42E,4756
17
+ onnxtr/models/engine.py,sha256=w1vzEduzVDHuxOb0JEkhPp2whrK7ViP03KZiNUNbe4I,4837
18
18
  onnxtr/models/zoo.py,sha256=Zcx0mOfMwUR2YAMd7ug06RvXeG2T1PzR2twS6y9X19A,5352
19
19
  onnxtr/models/classification/__init__.py,sha256=h1bZs55iLJBMATtzS4ntTKwfD6OGXBiiqGv_hEnOFnE,41
20
20
  onnxtr/models/classification/zoo.py,sha256=jzZMf7hKqN9omGAPHJR83rVDaaWhPm-Rk55Xn4bGaIs,3436
21
21
  onnxtr/models/classification/models/__init__.py,sha256=rohbM6ZQslfYchi7feZwwh-sX3XXRUhgtEJQeurAytQ,24
22
- onnxtr/models/classification/models/mobilenet.py,sha256=_hWUfQfjSLDPT2v_Ru6KcNZYMRTSPBlFpOdgGeE2jD0,4880
22
+ onnxtr/models/classification/models/mobilenet.py,sha256=l6Ch7ZwL4tqoN94YhSmudY6XYl5fIILzzu4T9JUwZKs,4881
23
23
  onnxtr/models/classification/predictor/__init__.py,sha256=ERmmOxz_9mUkIuccNbzUa5Y6gVLLVDdyc4cCxbCCUbY,20
24
24
  onnxtr/models/classification/predictor/base.py,sha256=Xfaj2XlaJuQ2R81XqF5RB0Wcvzd4wh7Z6j1ifn2niFc,2097
25
25
  onnxtr/models/detection/__init__.py,sha256=h1bZs55iLJBMATtzS4ntTKwfD6OGXBiiqGv_hEnOFnE,41
@@ -28,16 +28,18 @@ onnxtr/models/detection/zoo.py,sha256=5kz4l67Xkr4YTDoI2wDTiI6HSaB926zfua0SZU-Kaw
28
28
  onnxtr/models/detection/_utils/__init__.py,sha256=oPkIYbySSbLsOk02wVPNO9bUuywC47YjaenfyTwfOsw,20
29
29
  onnxtr/models/detection/_utils/base.py,sha256=fOWnvBKluWKTNXSBKg3U6ckzYuF7onEKQ4AvheuTJQk,2346
30
30
  onnxtr/models/detection/models/__init__.py,sha256=6Ea6knYrVCR2jAmPlsVWmCdHe-c6lSRETSAuZGfhx8I,85
31
- onnxtr/models/detection/models/differentiable_binarization.py,sha256=5ZeO3RRFMvLLZ4TpK01xUdxTTFhXvywjrNBbjASxgLY,6734
32
- onnxtr/models/detection/models/fast.py,sha256=2umsWdwPV91q6PyNrlZPbdi9DIk7dbmZWcLOMkD1EUg,6293
33
- onnxtr/models/detection/models/linknet.py,sha256=Wd4PbKMJlOZ20fXrZcqPYtdGETSKGXYAKEqBVrVWHEE,6771
31
+ onnxtr/models/detection/models/differentiable_binarization.py,sha256=bJ_bkeDBweY_bfyzI681rx2BpE4BcgDZe49M1FPJJig,6736
32
+ onnxtr/models/detection/models/fast.py,sha256=VkwboSA7IHCXCnxUDwMTEbxXWdrpCM477PY8nO2tPOI,6294
33
+ onnxtr/models/detection/models/linknet.py,sha256=aVRkCVvMDO74izdCFZRPtub7AJkxZntpsqqFrxMr8ts,6772
34
34
  onnxtr/models/detection/postprocessor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
35
  onnxtr/models/detection/postprocessor/base.py,sha256=FIhSNktNLQjGWup3xEMaOCjKQmRvtt0h8M9IFQk_5jM,5823
36
36
  onnxtr/models/detection/predictor/__init__.py,sha256=ERmmOxz_9mUkIuccNbzUa5Y6gVLLVDdyc4cCxbCCUbY,20
37
37
  onnxtr/models/detection/predictor/base.py,sha256=bt8M6I14tWC9DYjrFrqg-AU5u670_uPpuC7LmcegcCQ,2328
38
+ onnxtr/models/factory/__init__.py,sha256=cKPoH2V2157lLMTR2zsljG3_IQHziodqR-XK_LG0D_I,19
39
+ onnxtr/models/factory/hub.py,sha256=Fk6pX9VJD422rnVgLh37o136T_0YAsQFzY2dQplDfa4,7176
38
40
  onnxtr/models/predictor/__init__.py,sha256=XL25XkRkgyK7mldF-CWhg2MMakSdP5vLpDLwL59hphk,25
39
- onnxtr/models/predictor/base.py,sha256=VUs1OIsb8FW91U1ehB1sBaxG4Suz8iS-Ut50Zt6_SHo,8860
40
- onnxtr/models/predictor/predictor.py,sha256=etxgAvT8cYhboPyHiDRO0BL1rBoTw5lL1vhZP4dHWqw,6247
41
+ onnxtr/models/predictor/base.py,sha256=ZutI4iNUWk5I5wFfzip89JEDl0SmN7W7hCWRmVec38w,8813
42
+ onnxtr/models/predictor/predictor.py,sha256=pfyTu2qidlPOpXyNKkh20cZefWYUZlF3VEmzrsQr2K8,6368
41
43
  onnxtr/models/preprocessor/__init__.py,sha256=ERmmOxz_9mUkIuccNbzUa5Y6gVLLVDdyc4cCxbCCUbY,20
42
44
  onnxtr/models/preprocessor/base.py,sha256=8ZCKsB-o9uRaUm0x4x9FYpYxLXpwHyq2nVv_TlRgaMw,3990
43
45
  onnxtr/models/recognition/__init__.py,sha256=h1bZs55iLJBMATtzS4ntTKwfD6OGXBiiqGv_hEnOFnE,41
@@ -45,11 +47,11 @@ onnxtr/models/recognition/core.py,sha256=0Q1dVXqRcDUr_ycT5tpoSH9-zuDF58GtnmxWpUS
45
47
  onnxtr/models/recognition/utils.py,sha256=04abbjx-_OuF5iEANWIAOK3tQQl1tExPmBQx4IG04Lc,3569
46
48
  onnxtr/models/recognition/zoo.py,sha256=144aDgOpieatiVB0FO-otCNOAKS13AedLk7PWt4Z02M,2521
47
49
  onnxtr/models/recognition/models/__init__.py,sha256=IXfiuzzkft8O1CpBZWYTpFw19y49mt5rJ_iGSdaWiU0,105
48
- onnxtr/models/recognition/models/crnn.py,sha256=JyQ43NEiWj2Vzd8z1oVv_G66xn59ClZ63njowQaAs0g,8963
49
- onnxtr/models/recognition/models/master.py,sha256=-xnNM-5DPnbOH9b9mXPwU2Nknq7h1H0GXsdd2NWHFnM,4777
50
- onnxtr/models/recognition/models/parseq.py,sha256=1n3Qvif2763h7H7B2BKovHiFpgan4-bXMntc1O8XuPE,4577
51
- onnxtr/models/recognition/models/sar.py,sha256=Mc8axoyJaAlbdindvLLeOQCLp_p_m5kMZ9XHKzupo_E,4588
52
- onnxtr/models/recognition/models/vitstr.py,sha256=mrLpGUS2mrsjCfWdwbMkWgZagTURKSr0qS8JrwFTJzs,6054
50
+ onnxtr/models/recognition/models/crnn.py,sha256=rTMh_stR_4oKJKHKDCTEssQsXW56meYhWHahkaDPYpc,8965
51
+ onnxtr/models/recognition/models/master.py,sha256=UTsd2hSLrnTeafisVgdumAiJrpAeBm-WwYFI2ZEYERw,4778
52
+ onnxtr/models/recognition/models/parseq.py,sha256=nn-LsqQ_n1bmyE_QmVMgciillIkHlcpr8OFOunOQthQ,4579
53
+ onnxtr/models/recognition/models/sar.py,sha256=yEQ9_bH2kcjPr8iI-9Doq_Bm2SKhBCOeiRMv3IXp6mY,4590
54
+ onnxtr/models/recognition/models/vitstr.py,sha256=D9PR2N7IjhIh_YdPCSzlGRW91c3hrn2tCE_UTd89nxg,6055
53
55
  onnxtr/models/recognition/predictor/__init__.py,sha256=ERmmOxz_9mUkIuccNbzUa5Y6gVLLVDdyc4cCxbCCUbY,20
54
56
  onnxtr/models/recognition/predictor/_utils.py,sha256=ZNm5I7ibiWfTlz302uiifCkUOu65YWa-oUBUMPrrUuQ,3406
55
57
  onnxtr/models/recognition/predictor/base.py,sha256=YvqSNEM3rCEttxl6hsC9zl1R97N9zO2WZfD5_-nfkR0,2483
@@ -64,10 +66,10 @@ onnxtr/utils/multithreading.py,sha256=30T7AylM3rb52ZEI3Pk1pfB0VYraTbc7yO2vNODVVF
64
66
  onnxtr/utils/reconstitution.py,sha256=Hx1_ddLevKLzuxXc19UelPdsGlAwqi4f6vRSYKHDUB4,2617
65
67
  onnxtr/utils/repr.py,sha256=kfbjGL6KymGT8spo2UL4FJXZ0XRwa7CO7Y1dTVR8dIk,2129
66
68
  onnxtr/utils/visualization.py,sha256=CX09qvDnNIw3BFW5F3jM4R9OcpLWAeZyoDyTAOGRvls,9925
67
- onnxtr/utils/vocabs.py,sha256=SCQ4XQjbHSxunj1tg2iHRiPfE8OaTAMhcJbKq5BNvFs,3138
68
- onnxtr-0.3.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
69
- onnxtr-0.3.2.dist-info/METADATA,sha256=I9n5apYunvpxpSy36h-UtfNYl8eW3WOLpnPujaKUzgo,29802
70
- onnxtr-0.3.2.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
71
- onnxtr-0.3.2.dist-info/top_level.txt,sha256=r_MSUTpspp4pWEEWvly-s7ZkfCg1KwrK6-kBlXkWKU8,7
72
- onnxtr-0.3.2.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
73
- onnxtr-0.3.2.dist-info/RECORD,,
69
+ onnxtr/utils/vocabs.py,sha256=9Ufmjf7OczWb0931NjWTL7owXLYOKn5x0ulaoVeJGn8,3855
70
+ onnxtr-0.4.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
71
+ onnxtr-0.4.1.dist-info/METADATA,sha256=ghYrvvMe49613vZHcXr8qw6e8o7aoVD4uocdcKDaRYU,31723
72
+ onnxtr-0.4.1.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
73
+ onnxtr-0.4.1.dist-info/top_level.txt,sha256=r_MSUTpspp4pWEEWvly-s7ZkfCg1KwrK6-kBlXkWKU8,7
74
+ onnxtr-0.4.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
75
+ onnxtr-0.4.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (70.2.0)
2
+ Generator: setuptools (73.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5