onnxtr 0.5.0__tar.gz → 0.5.1__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.
- {onnxtr-0.5.0 → onnxtr-0.5.1}/PKG-INFO +2 -1
- {onnxtr-0.5.0 → onnxtr-0.5.1}/README.md +1 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/elements.py +11 -3
- onnxtr-0.5.1/onnxtr/utils/reconstitution.py +173 -0
- onnxtr-0.5.1/onnxtr/version.py +1 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/PKG-INFO +2 -1
- {onnxtr-0.5.0 → onnxtr-0.5.1}/pyproject.toml +2 -1
- {onnxtr-0.5.0 → onnxtr-0.5.1}/setup.py +1 -1
- onnxtr-0.5.0/onnxtr/utils/reconstitution.py +0 -70
- onnxtr-0.5.0/onnxtr/version.py +0 -1
- {onnxtr-0.5.0 → onnxtr-0.5.1}/LICENSE +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/contrib/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/contrib/artefacts.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/contrib/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/file_utils.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/html.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/image.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/pdf.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/io/reader.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/_utils.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/builder.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/models/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/models/mobilenet.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/predictor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/predictor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/classification/zoo.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/_utils/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/_utils/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/core.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/models/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/models/differentiable_binarization.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/models/fast.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/models/linknet.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/postprocessor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/postprocessor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/predictor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/predictor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/detection/zoo.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/engine.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/factory/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/factory/hub.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/predictor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/predictor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/predictor/predictor.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/preprocessor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/preprocessor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/core.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/crnn.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/master.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/parseq.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/sar.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/models/vitstr.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/predictor/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/predictor/_utils.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/predictor/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/utils.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/recognition/zoo.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/models/zoo.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/py.typed +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/transforms/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/transforms/base.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/__init__.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/common_types.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/data.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/fonts.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/geometry.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/multithreading.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/repr.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/visualization.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr/utils/vocabs.py +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/SOURCES.txt +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/dependency_links.txt +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/requires.txt +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/top_level.txt +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/onnxtr.egg-info/zip-safe +0 -0
- {onnxtr-0.5.0 → onnxtr-0.5.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: onnxtr
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.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
|
|
@@ -285,6 +285,7 @@ Requires-Dist: pre-commit>=2.17.0; extra == "dev"
|
|
|
285
285
|
[](https://app.codacy.com/gh/felixdittrich92/OnnxTR/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
286
286
|
[](https://www.codefactor.io/repository/github/felixdittrich92/onnxtr)
|
|
287
287
|
[](https://pypi.org/project/OnnxTR/)
|
|
288
|
+
[](https://huggingface.co/spaces/Felix92/OnnxTR-OCR)
|
|
288
289
|
|
|
289
290
|
> :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.
|
|
290
291
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://app.codacy.com/gh/felixdittrich92/OnnxTR/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
9
9
|
[](https://www.codefactor.io/repository/github/felixdittrich92/onnxtr)
|
|
10
10
|
[](https://pypi.org/project/OnnxTR/)
|
|
11
|
+
[](https://huggingface.co/spaces/Felix92/OnnxTR-OCR)
|
|
11
12
|
|
|
12
13
|
> :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.
|
|
13
14
|
|
|
@@ -163,7 +163,7 @@ class Line(Element):
|
|
|
163
163
|
if geometry is None:
|
|
164
164
|
# Check whether this is a rotated or straight box
|
|
165
165
|
box_resolution_fn = resolve_enclosing_rbbox if len(words[0].geometry) == 4 else resolve_enclosing_bbox
|
|
166
|
-
geometry = box_resolution_fn([w.geometry for w in words]) # type: ignore[
|
|
166
|
+
geometry = box_resolution_fn([w.geometry for w in words]) # type: ignore[misc]
|
|
167
167
|
|
|
168
168
|
super().__init__(words=words)
|
|
169
169
|
self.geometry = geometry
|
|
@@ -216,7 +216,7 @@ class Block(Element):
|
|
|
216
216
|
box_resolution_fn = (
|
|
217
217
|
resolve_enclosing_rbbox if isinstance(lines[0].geometry, np.ndarray) else resolve_enclosing_bbox
|
|
218
218
|
)
|
|
219
|
-
geometry = box_resolution_fn(line_boxes + artefact_boxes) # type: ignore
|
|
219
|
+
geometry = box_resolution_fn(line_boxes + artefact_boxes) # type: ignore
|
|
220
220
|
|
|
221
221
|
super().__init__(lines=lines, artefacts=artefacts)
|
|
222
222
|
self.geometry = geometry
|
|
@@ -294,6 +294,10 @@ class Page(Element):
|
|
|
294
294
|
def synthesize(self, **kwargs) -> np.ndarray:
|
|
295
295
|
"""Synthesize the page from the predictions
|
|
296
296
|
|
|
297
|
+
Args:
|
|
298
|
+
----
|
|
299
|
+
**kwargs: keyword arguments passed to the `synthesize_page` method
|
|
300
|
+
|
|
297
301
|
Returns
|
|
298
302
|
-------
|
|
299
303
|
synthesized page
|
|
@@ -442,11 +446,15 @@ class Document(Element):
|
|
|
442
446
|
def synthesize(self, **kwargs) -> List[np.ndarray]:
|
|
443
447
|
"""Synthesize all pages from their predictions
|
|
444
448
|
|
|
449
|
+
Args:
|
|
450
|
+
----
|
|
451
|
+
**kwargs: keyword arguments passed to the `Page.synthesize` method
|
|
452
|
+
|
|
445
453
|
Returns
|
|
446
454
|
-------
|
|
447
455
|
list of synthesized pages
|
|
448
456
|
"""
|
|
449
|
-
return [page.synthesize() for page in self.pages]
|
|
457
|
+
return [page.synthesize(**kwargs) for page in self.pages]
|
|
450
458
|
|
|
451
459
|
def export_as_xml(self, **kwargs) -> List[Tuple[bytes, ET.ElementTree]]:
|
|
452
460
|
"""Export the document as XML (hOCR-format)
|
|
@@ -0,0 +1,173 @@
|
|
|
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
|
+
import logging
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
from anyascii import anyascii
|
|
10
|
+
from PIL import Image, ImageDraw
|
|
11
|
+
|
|
12
|
+
from .fonts import get_font
|
|
13
|
+
|
|
14
|
+
__all__ = ["synthesize_page"]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# Global variable to avoid multiple warnings
|
|
18
|
+
ROTATION_WARNING = False
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _warn_rotation(entry: Dict[str, Any]) -> None: # pragma: no cover
|
|
22
|
+
global ROTATION_WARNING
|
|
23
|
+
if not ROTATION_WARNING and len(entry["geometry"]) == 4:
|
|
24
|
+
logging.warning("Polygons with larger rotations will lead to inaccurate rendering")
|
|
25
|
+
ROTATION_WARNING = True
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _synthesize(
|
|
29
|
+
response: Image.Image,
|
|
30
|
+
entry: Dict[str, Any],
|
|
31
|
+
w: int,
|
|
32
|
+
h: int,
|
|
33
|
+
draw_proba: bool = False,
|
|
34
|
+
font_family: Optional[str] = None,
|
|
35
|
+
smoothing_factor: float = 0.75,
|
|
36
|
+
min_font_size: int = 6,
|
|
37
|
+
max_font_size: int = 50,
|
|
38
|
+
) -> Image.Image:
|
|
39
|
+
if len(entry["geometry"]) == 2:
|
|
40
|
+
(xmin, ymin), (xmax, ymax) = entry["geometry"]
|
|
41
|
+
polygon = [(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]
|
|
42
|
+
else:
|
|
43
|
+
polygon = entry["geometry"]
|
|
44
|
+
|
|
45
|
+
# Calculate the bounding box of the word
|
|
46
|
+
x_coords, y_coords = zip(*polygon)
|
|
47
|
+
xmin, ymin, xmax, ymax = (
|
|
48
|
+
int(round(w * min(x_coords))),
|
|
49
|
+
int(round(h * min(y_coords))),
|
|
50
|
+
int(round(w * max(x_coords))),
|
|
51
|
+
int(round(h * max(y_coords))),
|
|
52
|
+
)
|
|
53
|
+
word_width = xmax - xmin
|
|
54
|
+
word_height = ymax - ymin
|
|
55
|
+
|
|
56
|
+
# If lines are provided instead of words, concatenate the word entries
|
|
57
|
+
if "words" in entry:
|
|
58
|
+
word_text = " ".join(word["value"] for word in entry["words"])
|
|
59
|
+
else:
|
|
60
|
+
word_text = entry["value"]
|
|
61
|
+
# Find the optimal font size
|
|
62
|
+
try:
|
|
63
|
+
font_size = min(word_height, max_font_size)
|
|
64
|
+
font = get_font(font_family, font_size)
|
|
65
|
+
text_width, text_height = font.getbbox(word_text)[2:4]
|
|
66
|
+
|
|
67
|
+
while (text_width > word_width or text_height > word_height) and font_size > min_font_size:
|
|
68
|
+
font_size = max(int(font_size * smoothing_factor), min_font_size)
|
|
69
|
+
font = get_font(font_family, font_size)
|
|
70
|
+
text_width, text_height = font.getbbox(word_text)[2:4]
|
|
71
|
+
except ValueError: # pragma: no cover
|
|
72
|
+
font = get_font(font_family, min_font_size)
|
|
73
|
+
|
|
74
|
+
# Create a mask for the word
|
|
75
|
+
mask = Image.new("L", (w, h), 0)
|
|
76
|
+
ImageDraw.Draw(mask).polygon([(int(round(w * x)), int(round(h * y))) for x, y in polygon], fill=255)
|
|
77
|
+
|
|
78
|
+
# Draw the word text
|
|
79
|
+
d = ImageDraw.Draw(response)
|
|
80
|
+
try:
|
|
81
|
+
try:
|
|
82
|
+
d.text((xmin, ymin), word_text, font=font, fill=(0, 0, 0), anchor="lt")
|
|
83
|
+
except UnicodeEncodeError: # pragma: no cover
|
|
84
|
+
d.text((xmin, ymin), anyascii(word_text), font=font, fill=(0, 0, 0), anchor="lt")
|
|
85
|
+
# Catch generic exceptions to avoid crashing the whole rendering
|
|
86
|
+
except Exception: # pragma: no cover
|
|
87
|
+
logging.warning(f"Could not render word: {word_text}")
|
|
88
|
+
|
|
89
|
+
if draw_proba:
|
|
90
|
+
confidence = (
|
|
91
|
+
entry["confidence"]
|
|
92
|
+
if "confidence" in entry
|
|
93
|
+
else sum(w["confidence"] for w in entry["words"]) / len(entry["words"])
|
|
94
|
+
)
|
|
95
|
+
p = int(255 * confidence)
|
|
96
|
+
color = (255 - p, 0, p) # Red to blue gradient based on probability
|
|
97
|
+
d.rectangle([(xmin, ymin), (xmax, ymax)], outline=color, width=2)
|
|
98
|
+
|
|
99
|
+
prob_font = get_font(font_family, 20)
|
|
100
|
+
prob_text = f"{confidence:.2f}"
|
|
101
|
+
prob_text_width, prob_text_height = prob_font.getbbox(prob_text)[2:4]
|
|
102
|
+
|
|
103
|
+
# Position the probability slightly above the bounding box
|
|
104
|
+
prob_x_offset = (word_width - prob_text_width) // 2
|
|
105
|
+
prob_y_offset = ymin - prob_text_height - 2
|
|
106
|
+
prob_y_offset = max(0, prob_y_offset)
|
|
107
|
+
|
|
108
|
+
d.text((xmin + prob_x_offset, prob_y_offset), prob_text, font=prob_font, fill=color, anchor="lt")
|
|
109
|
+
|
|
110
|
+
return response
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def synthesize_page(
|
|
114
|
+
page: Dict[str, Any],
|
|
115
|
+
draw_proba: bool = False,
|
|
116
|
+
font_family: Optional[str] = None,
|
|
117
|
+
smoothing_factor: float = 0.95,
|
|
118
|
+
min_font_size: int = 8,
|
|
119
|
+
max_font_size: int = 50,
|
|
120
|
+
) -> np.ndarray:
|
|
121
|
+
"""Draw a the content of the element page (OCR response) on a blank page.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
----
|
|
125
|
+
page: exported Page object to represent
|
|
126
|
+
draw_proba: if True, draw words in colors to represent confidence. Blue: p=1, red: p=0
|
|
127
|
+
font_family: family of the font
|
|
128
|
+
smoothing_factor: factor to smooth the font size
|
|
129
|
+
min_font_size: minimum font size
|
|
130
|
+
max_font_size: maximum font size
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
-------
|
|
134
|
+
the synthesized page
|
|
135
|
+
"""
|
|
136
|
+
# Draw template
|
|
137
|
+
h, w = page["dimensions"]
|
|
138
|
+
response = Image.new("RGB", (w, h), color=(255, 255, 255))
|
|
139
|
+
|
|
140
|
+
for block in page["blocks"]:
|
|
141
|
+
# If lines are provided use these to get better rendering results
|
|
142
|
+
if len(block["lines"]) > 1:
|
|
143
|
+
for line in block["lines"]:
|
|
144
|
+
_warn_rotation(block) # pragma: no cover
|
|
145
|
+
response = _synthesize(
|
|
146
|
+
response=response,
|
|
147
|
+
entry=line,
|
|
148
|
+
w=w,
|
|
149
|
+
h=h,
|
|
150
|
+
draw_proba=draw_proba,
|
|
151
|
+
font_family=font_family,
|
|
152
|
+
smoothing_factor=smoothing_factor,
|
|
153
|
+
min_font_size=min_font_size,
|
|
154
|
+
max_font_size=max_font_size,
|
|
155
|
+
)
|
|
156
|
+
# Otherwise, draw each word
|
|
157
|
+
else:
|
|
158
|
+
for line in block["lines"]:
|
|
159
|
+
_warn_rotation(block) # pragma: no cover
|
|
160
|
+
for word in line["words"]:
|
|
161
|
+
response = _synthesize(
|
|
162
|
+
response=response,
|
|
163
|
+
entry=word,
|
|
164
|
+
w=w,
|
|
165
|
+
h=h,
|
|
166
|
+
draw_proba=draw_proba,
|
|
167
|
+
font_family=font_family,
|
|
168
|
+
smoothing_factor=smoothing_factor,
|
|
169
|
+
min_font_size=min_font_size,
|
|
170
|
+
max_font_size=max_font_size,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return np.array(response, dtype=np.uint8)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = 'v0.5.1'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: onnxtr
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.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
|
|
@@ -285,6 +285,7 @@ Requires-Dist: pre-commit>=2.17.0; extra == "dev"
|
|
|
285
285
|
[](https://app.codacy.com/gh/felixdittrich92/OnnxTR/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
|
|
286
286
|
[](https://www.codefactor.io/repository/github/felixdittrich92/onnxtr)
|
|
287
287
|
[](https://pypi.org/project/OnnxTR/)
|
|
288
|
+
[](https://huggingface.co/spaces/Felix92/OnnxTR-OCR)
|
|
288
289
|
|
|
289
290
|
> :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.
|
|
290
291
|
|
|
@@ -107,7 +107,7 @@ changelog = "https://github.com/felixdittrich92/OnnxTR/releases"
|
|
|
107
107
|
zip-safe = true
|
|
108
108
|
|
|
109
109
|
[tool.setuptools.packages.find]
|
|
110
|
-
exclude = ["docs*", "tests*", "scripts*"]
|
|
110
|
+
exclude = ["docs*", "tests*", "scripts*", "demo*"]
|
|
111
111
|
|
|
112
112
|
[tool.setuptools.package-data]
|
|
113
113
|
onnxtr = ["py.typed"]
|
|
@@ -166,6 +166,7 @@ known-third-party = ["onnxruntime", "cv2"]
|
|
|
166
166
|
"onnxtr/models/**.py" = ["N806", "F841"]
|
|
167
167
|
"tests/**.py" = ["D"]
|
|
168
168
|
"scripts/**.py" = ["D"]
|
|
169
|
+
"demo/**.py" = ["D"]
|
|
169
170
|
".github/**.py" = ["D"]
|
|
170
171
|
|
|
171
172
|
|
|
@@ -1,70 +0,0 @@
|
|
|
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
|
-
from typing import Any, Dict, Optional
|
|
6
|
-
|
|
7
|
-
import numpy as np
|
|
8
|
-
from anyascii import anyascii
|
|
9
|
-
from PIL import Image, ImageDraw
|
|
10
|
-
|
|
11
|
-
from .fonts import get_font
|
|
12
|
-
|
|
13
|
-
__all__ = ["synthesize_page"]
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def synthesize_page(
|
|
17
|
-
page: Dict[str, Any],
|
|
18
|
-
draw_proba: bool = False,
|
|
19
|
-
font_family: Optional[str] = None,
|
|
20
|
-
) -> np.ndarray:
|
|
21
|
-
"""Draw a the content of the element page (OCR response) on a blank page.
|
|
22
|
-
|
|
23
|
-
Args:
|
|
24
|
-
----
|
|
25
|
-
page: exported Page object to represent
|
|
26
|
-
draw_proba: if True, draw words in colors to represent confidence. Blue: p=1, red: p=0
|
|
27
|
-
font_size: size of the font, default font = 13
|
|
28
|
-
font_family: family of the font
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
-------
|
|
32
|
-
the synthesized page
|
|
33
|
-
"""
|
|
34
|
-
# Draw template
|
|
35
|
-
h, w = page["dimensions"]
|
|
36
|
-
response = 255 * np.ones((h, w, 3), dtype=np.int32)
|
|
37
|
-
|
|
38
|
-
# Draw each word
|
|
39
|
-
for block in page["blocks"]:
|
|
40
|
-
for line in block["lines"]:
|
|
41
|
-
for word in line["words"]:
|
|
42
|
-
# Get absolute word geometry
|
|
43
|
-
(xmin, ymin), (xmax, ymax) = word["geometry"]
|
|
44
|
-
xmin, xmax = int(round(w * xmin)), int(round(w * xmax))
|
|
45
|
-
ymin, ymax = int(round(h * ymin)), int(round(h * ymax))
|
|
46
|
-
|
|
47
|
-
# White drawing context adapted to font size, 0.75 factor to convert pts --> pix
|
|
48
|
-
font = get_font(font_family, int(0.75 * (ymax - ymin)))
|
|
49
|
-
img = Image.new("RGB", (xmax - xmin, ymax - ymin), color=(255, 255, 255))
|
|
50
|
-
d = ImageDraw.Draw(img)
|
|
51
|
-
# Draw in black the value of the word
|
|
52
|
-
try:
|
|
53
|
-
d.text((0, 0), word["value"], font=font, fill=(0, 0, 0))
|
|
54
|
-
except UnicodeEncodeError:
|
|
55
|
-
# When character cannot be encoded, use its anyascii version
|
|
56
|
-
d.text((0, 0), anyascii(word["value"]), font=font, fill=(0, 0, 0))
|
|
57
|
-
|
|
58
|
-
# Colorize if draw_proba
|
|
59
|
-
if draw_proba:
|
|
60
|
-
p = int(255 * word["confidence"])
|
|
61
|
-
mask = np.where(np.array(img) == 0, 1, 0)
|
|
62
|
-
proba: np.ndarray = np.array([255 - p, 0, p])
|
|
63
|
-
color = mask * proba[np.newaxis, np.newaxis, :]
|
|
64
|
-
white_mask = 255 * (1 - mask)
|
|
65
|
-
img = color + white_mask
|
|
66
|
-
|
|
67
|
-
# Write to response page
|
|
68
|
-
response[ymin:ymax, xmin:xmax, :] = np.array(img)
|
|
69
|
-
|
|
70
|
-
return response
|
onnxtr-0.5.0/onnxtr/version.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = 'v0.5.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|