deepdoctection 0.45.0__tar.gz → 0.46__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.
Potentially problematic release.
This version of deepdoctection might be problematic. Click here for more details.
- {deepdoctection-0.45.0 → deepdoctection-0.46}/PKG-INFO +5 -10
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/__init__.py +4 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/analyzer/config.py +3 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/analyzer/factory.py +16 -7
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/parallel_map.py +7 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/box.py +5 -5
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/image.py +5 -5
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/view.py +35 -14
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/cocometric.py +1 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/base.py +8 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/doctrocr.py +18 -2
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/hflayoutlm.py +6 -12
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tessocr.py +17 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/order.py +12 -6
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/refine.py +10 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/text.py +6 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/transform.py +3 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/file_utils.py +33 -4
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/logger.py +38 -1
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/transform.py +43 -18
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/viz.py +23 -14
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection.egg-info/PKG-INFO +5 -10
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection.egg-info/requires.txt +4 -9
- {deepdoctection-0.45.0 → deepdoctection-0.46}/setup.py +6 -7
- {deepdoctection-0.45.0 → deepdoctection-0.46}/LICENSE +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/README.md +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/analyzer/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/analyzer/dd.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/configs/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/configs/conf_dd_one.yaml +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/configs/conf_tesseract.yaml +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/configs/profiles.jsonl +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/base.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/common.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/custom.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/custom_serialize.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/serialize.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/dataflow/stats.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/annotation.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datapoint/convert.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/adapter.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/base.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/dataflow_builder.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/info.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/doclaynet.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/fintabnet.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/funsd.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/iiitar13k.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/layouttest.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/publaynet.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/pubtables1m.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/pubtabnet.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/rvlcdip.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/xfund.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/xsl/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/instances/xsl/pascal_voc.xsl +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/registry.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/datasets/save.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/accmetric.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/base.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/eval.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/registry.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/tedsmetric.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/eval/tp_eval_callback.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/d2detect.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/deskew.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/fastlang.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/hfdetr.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/hflm.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/model.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/pdftext.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/pt/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/pt/nms.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/pt/ptutils.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/texocr.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tfutils.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpcompat.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/common.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/config/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/config/config.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/backbone.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/generalized_rcnn.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_box.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_cascade.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_fpn.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_frcnn.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_mrcnn.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/modeling/model_rpn.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/predict.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/preproc.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/utils/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/utils/box_ops.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tp/tpfrcnn/utils/np_box_ops.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/extern/tpdetect.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/cats.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/cocostruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/d2struct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/hfstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/laylmstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/maputils.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/match.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/misc.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/pascalstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/prodigystruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/pubstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/tpstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/mapper/xfundstruct.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/anngen.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/base.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/common.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/concurrency.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/doctectionpipe.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/language.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/layout.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/lm.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/registry.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/segment.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/pipe/sub_layout.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/py.typed +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/train/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/train/d2_frcnn_train.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/train/hf_detr_train.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/train/hf_layoutlm_train.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/train/tp_frcnn_train.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/__init__.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/concurrency.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/context.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/develop.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/env_info.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/error.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/fs.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/identifier.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/metacfg.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/mocks.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/pdf_utils.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/settings.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/tqdm.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/types.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection/utils/utils.py +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection.egg-info/SOURCES.txt +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection.egg-info/dependency_links.txt +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/deepdoctection.egg-info/top_level.txt +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/setup.cfg +0 -0
- {deepdoctection-0.45.0 → deepdoctection-0.46}/tests/test_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deepdoctection
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.46
|
|
4
4
|
Summary: Repository for Document AI
|
|
5
5
|
Home-page: https://github.com/deepdoctection/deepdoctection
|
|
6
6
|
Author: Dr. Janis Meyer
|
|
@@ -19,18 +19,15 @@ Description-Content-Type: text/markdown
|
|
|
19
19
|
License-File: LICENSE
|
|
20
20
|
Requires-Dist: catalogue==2.0.10
|
|
21
21
|
Requires-Dist: huggingface_hub>=0.26.0
|
|
22
|
-
Requires-Dist: importlib-metadata>=5.0.0
|
|
23
22
|
Requires-Dist: jsonlines==3.1.0
|
|
24
23
|
Requires-Dist: lazy-imports==0.3.1
|
|
25
24
|
Requires-Dist: mock==4.0.3
|
|
26
|
-
Requires-Dist: networkx>=2.7.1
|
|
27
25
|
Requires-Dist: numpy>2.0
|
|
28
26
|
Requires-Dist: packaging>=20.0
|
|
29
27
|
Requires-Dist: Pillow>=10.0.0
|
|
30
28
|
Requires-Dist: pypdf>=6.0.0
|
|
31
29
|
Requires-Dist: pypdfium2>=4.30.0
|
|
32
30
|
Requires-Dist: pyyaml>=6.0.1
|
|
33
|
-
Requires-Dist: pyzmq>=16
|
|
34
31
|
Requires-Dist: scipy>=1.13.1
|
|
35
32
|
Requires-Dist: termcolor>=1.1
|
|
36
33
|
Requires-Dist: tabulate>=0.7.7
|
|
@@ -38,18 +35,15 @@ Requires-Dist: tqdm>=4.64.0
|
|
|
38
35
|
Provides-Extra: tf
|
|
39
36
|
Requires-Dist: catalogue==2.0.10; extra == "tf"
|
|
40
37
|
Requires-Dist: huggingface_hub>=0.26.0; extra == "tf"
|
|
41
|
-
Requires-Dist: importlib-metadata>=5.0.0; extra == "tf"
|
|
42
38
|
Requires-Dist: jsonlines==3.1.0; extra == "tf"
|
|
43
39
|
Requires-Dist: lazy-imports==0.3.1; extra == "tf"
|
|
44
40
|
Requires-Dist: mock==4.0.3; extra == "tf"
|
|
45
|
-
Requires-Dist: networkx>=2.7.1; extra == "tf"
|
|
46
41
|
Requires-Dist: numpy>2.0; extra == "tf"
|
|
47
42
|
Requires-Dist: packaging>=20.0; extra == "tf"
|
|
48
43
|
Requires-Dist: Pillow>=10.0.0; extra == "tf"
|
|
49
44
|
Requires-Dist: pypdf>=6.0.0; extra == "tf"
|
|
50
45
|
Requires-Dist: pypdfium2>=4.30.0; extra == "tf"
|
|
51
46
|
Requires-Dist: pyyaml>=6.0.1; extra == "tf"
|
|
52
|
-
Requires-Dist: pyzmq>=16; extra == "tf"
|
|
53
47
|
Requires-Dist: scipy>=1.13.1; extra == "tf"
|
|
54
48
|
Requires-Dist: termcolor>=1.1; extra == "tf"
|
|
55
49
|
Requires-Dist: tabulate>=0.7.7; extra == "tf"
|
|
@@ -62,25 +56,24 @@ Requires-Dist: python-doctr==0.10.0; extra == "tf"
|
|
|
62
56
|
Requires-Dist: pycocotools>=2.0.2; extra == "tf"
|
|
63
57
|
Requires-Dist: boto3==1.34.102; extra == "tf"
|
|
64
58
|
Requires-Dist: pdfplumber>=0.11.0; extra == "tf"
|
|
59
|
+
Requires-Dist: pyzmq>=16; extra == "tf"
|
|
65
60
|
Requires-Dist: jdeskew>=0.2.2; extra == "tf"
|
|
66
61
|
Requires-Dist: apted==1.0.3; extra == "tf"
|
|
67
62
|
Requires-Dist: distance==0.1.3; extra == "tf"
|
|
68
63
|
Requires-Dist: lxml>=4.9.1; extra == "tf"
|
|
64
|
+
Requires-Dist: networkx>=2.7.1; extra == "tf"
|
|
69
65
|
Provides-Extra: pt
|
|
70
66
|
Requires-Dist: catalogue==2.0.10; extra == "pt"
|
|
71
67
|
Requires-Dist: huggingface_hub>=0.26.0; extra == "pt"
|
|
72
|
-
Requires-Dist: importlib-metadata>=5.0.0; extra == "pt"
|
|
73
68
|
Requires-Dist: jsonlines==3.1.0; extra == "pt"
|
|
74
69
|
Requires-Dist: lazy-imports==0.3.1; extra == "pt"
|
|
75
70
|
Requires-Dist: mock==4.0.3; extra == "pt"
|
|
76
|
-
Requires-Dist: networkx>=2.7.1; extra == "pt"
|
|
77
71
|
Requires-Dist: numpy>2.0; extra == "pt"
|
|
78
72
|
Requires-Dist: packaging>=20.0; extra == "pt"
|
|
79
73
|
Requires-Dist: Pillow>=10.0.0; extra == "pt"
|
|
80
74
|
Requires-Dist: pypdf>=6.0.0; extra == "pt"
|
|
81
75
|
Requires-Dist: pypdfium2>=4.30.0; extra == "pt"
|
|
82
76
|
Requires-Dist: pyyaml>=6.0.1; extra == "pt"
|
|
83
|
-
Requires-Dist: pyzmq>=16; extra == "pt"
|
|
84
77
|
Requires-Dist: scipy>=1.13.1; extra == "pt"
|
|
85
78
|
Requires-Dist: termcolor>=1.1; extra == "pt"
|
|
86
79
|
Requires-Dist: tabulate>=0.7.7; extra == "pt"
|
|
@@ -92,10 +85,12 @@ Requires-Dist: python-doctr==0.10.0; extra == "pt"
|
|
|
92
85
|
Requires-Dist: pycocotools>=2.0.2; extra == "pt"
|
|
93
86
|
Requires-Dist: boto3==1.34.102; extra == "pt"
|
|
94
87
|
Requires-Dist: pdfplumber>=0.11.0; extra == "pt"
|
|
88
|
+
Requires-Dist: pyzmq>=16; extra == "pt"
|
|
95
89
|
Requires-Dist: jdeskew>=0.2.2; extra == "pt"
|
|
96
90
|
Requires-Dist: apted==1.0.3; extra == "pt"
|
|
97
91
|
Requires-Dist: distance==0.1.3; extra == "pt"
|
|
98
92
|
Requires-Dist: lxml>=4.9.1; extra == "pt"
|
|
93
|
+
Requires-Dist: networkx>=2.7.1; extra == "pt"
|
|
99
94
|
Provides-Extra: docs
|
|
100
95
|
Requires-Dist: tensorpack==0.11; extra == "docs"
|
|
101
96
|
Requires-Dist: boto3==1.34.102; extra == "docs"
|
|
@@ -25,7 +25,7 @@ from .utils.logger import LoggingRecord, logger
|
|
|
25
25
|
|
|
26
26
|
# pylint: enable=wrong-import-position
|
|
27
27
|
|
|
28
|
-
__version__ = "0.
|
|
28
|
+
__version__ = "0.46"
|
|
29
29
|
|
|
30
30
|
_IMPORT_STRUCTURE = {
|
|
31
31
|
"analyzer": ["config_sanity_checks", "get_dd_analyzer", "ServiceFactory", "update_cfg_from_defaults"],
|
|
@@ -271,6 +271,7 @@ _IMPORT_STRUCTURE = {
|
|
|
271
271
|
"MultiThreadPipelineComponent",
|
|
272
272
|
"DoctectionPipe",
|
|
273
273
|
"LanguageDetectionService",
|
|
274
|
+
"skip_if_category_or_service_extracted",
|
|
274
275
|
"ImageLayoutService",
|
|
275
276
|
"LMTokenClassifierService",
|
|
276
277
|
"LMSequenceClassifierService",
|
|
@@ -310,12 +311,14 @@ _IMPORT_STRUCTURE = {
|
|
|
310
311
|
"get_tensorpack_requirement",
|
|
311
312
|
"pytorch_available",
|
|
312
313
|
"get_pytorch_requirement",
|
|
314
|
+
"pyzmq_available",
|
|
313
315
|
"lxml_available",
|
|
314
316
|
"get_lxml_requirement",
|
|
315
317
|
"apted_available",
|
|
316
318
|
"get_apted_requirement",
|
|
317
319
|
"distance_available",
|
|
318
320
|
"get_distance_requirement",
|
|
321
|
+
"networkx_available",
|
|
319
322
|
"numpy_v1_available",
|
|
320
323
|
"get_numpy_v1_requirement",
|
|
321
324
|
"transformers_available",
|
|
@@ -526,6 +526,9 @@ cfg.USE_LM_SEQUENCE_CLASS = False
|
|
|
526
526
|
# Enables a token classification pipeline component, e.g. a LayoutLM or Bert-like model
|
|
527
527
|
cfg.USE_LM_TOKEN_CLASS = False
|
|
528
528
|
|
|
529
|
+
# Specifies the selection of the rotation model. There are two models available: A rotation estimator
|
|
530
|
+
# based on Tesseract ('tesseract'), and a rotation estimator based on DocTr ('doctr').
|
|
531
|
+
cfg.ROTATOR.MODEL = "tesseract"
|
|
529
532
|
|
|
530
533
|
# Relevant when LIB = TF. Specifies the layout detection model.
|
|
531
534
|
# This model should detect multiple or single objects across an entire page.
|
|
@@ -22,13 +22,13 @@
|
|
|
22
22
|
from __future__ import annotations
|
|
23
23
|
|
|
24
24
|
from os import environ
|
|
25
|
-
from typing import TYPE_CHECKING, Union
|
|
25
|
+
from typing import TYPE_CHECKING, Literal, Union
|
|
26
26
|
|
|
27
27
|
from lazy_imports import try_import
|
|
28
28
|
|
|
29
29
|
from ..extern.base import ImageTransformer, ObjectDetector, PdfMiner
|
|
30
30
|
from ..extern.d2detect import D2FrcnnDetector, D2FrcnnTracingDetector
|
|
31
|
-
from ..extern.doctrocr import DoctrTextlineDetector, DoctrTextRecognizer
|
|
31
|
+
from ..extern.doctrocr import DocTrRotationTransformer, DoctrTextlineDetector, DoctrTextRecognizer
|
|
32
32
|
from ..extern.hfdetr import HFDetrDerivedDetector
|
|
33
33
|
from ..extern.hflayoutlm import (
|
|
34
34
|
HFLayoutLmSequenceClassifier,
|
|
@@ -78,6 +78,7 @@ if TYPE_CHECKING:
|
|
|
78
78
|
from ..extern.hflayoutlm import LayoutSequenceModels, LayoutTokenModels
|
|
79
79
|
from ..extern.hflm import LmSequenceModels, LmTokenModels
|
|
80
80
|
|
|
81
|
+
RotationTransformer = Union[TesseractRotationTransformer, DocTrRotationTransformer]
|
|
81
82
|
|
|
82
83
|
__all__ = [
|
|
83
84
|
"ServiceFactory",
|
|
@@ -190,24 +191,32 @@ class ServiceFactory:
|
|
|
190
191
|
return ServiceFactory._build_layout_detector(config, mode)
|
|
191
192
|
|
|
192
193
|
@staticmethod
|
|
193
|
-
def _build_rotation_detector() ->
|
|
194
|
+
def _build_rotation_detector(rotator_name: Literal["tesseract", "doctr"]) -> RotationTransformer:
|
|
194
195
|
"""
|
|
195
196
|
Building a rotation detector.
|
|
196
197
|
|
|
197
198
|
Returns:
|
|
198
199
|
TesseractRotationTransformer: Rotation detector instance.
|
|
199
200
|
"""
|
|
200
|
-
|
|
201
|
+
|
|
202
|
+
if rotator_name == "tesseract":
|
|
203
|
+
return TesseractRotationTransformer()
|
|
204
|
+
if rotator_name == "doctr":
|
|
205
|
+
return DocTrRotationTransformer()
|
|
206
|
+
raise ValueError(
|
|
207
|
+
f"You have chosen rotator_name: {rotator_name} which is not allowed. Only tesseract or "
|
|
208
|
+
f"doctr are allowed."
|
|
209
|
+
)
|
|
201
210
|
|
|
202
211
|
@staticmethod
|
|
203
|
-
def build_rotation_detector() ->
|
|
212
|
+
def build_rotation_detector(rotator_name: Literal["tesseract", "doctr"]) -> RotationTransformer:
|
|
204
213
|
"""
|
|
205
214
|
Building a rotation detector.
|
|
206
215
|
|
|
207
216
|
Returns:
|
|
208
217
|
TesseractRotationTransformer: Rotation detector instance.
|
|
209
218
|
"""
|
|
210
|
-
return ServiceFactory._build_rotation_detector()
|
|
219
|
+
return ServiceFactory._build_rotation_detector(rotator_name)
|
|
211
220
|
|
|
212
221
|
@staticmethod
|
|
213
222
|
def _build_transform_service(transform_predictor: ImageTransformer) -> SimpleTransformService:
|
|
@@ -1123,7 +1132,7 @@ class ServiceFactory:
|
|
|
1123
1132
|
pipe_component_list: list[PipelineComponent] = []
|
|
1124
1133
|
|
|
1125
1134
|
if config.USE_ROTATOR:
|
|
1126
|
-
rotation_detector = ServiceFactory.build_rotation_detector()
|
|
1135
|
+
rotation_detector = ServiceFactory.build_rotation_detector(config.ROTATOR.MODEL)
|
|
1127
1136
|
transform_service = ServiceFactory.build_transform_service(transform_predictor=rotation_detector)
|
|
1128
1137
|
pipe_component_list.append(transform_service)
|
|
1129
1138
|
|
|
@@ -24,15 +24,19 @@ from abc import ABC, abstractmethod
|
|
|
24
24
|
from contextlib import contextmanager
|
|
25
25
|
from typing import Any, Callable, Iterator, no_type_check
|
|
26
26
|
|
|
27
|
-
import
|
|
27
|
+
from lazy_imports import try_import
|
|
28
28
|
|
|
29
29
|
from ..utils.concurrency import StoppableThread, enable_death_signal, start_proc_mask_signal
|
|
30
30
|
from ..utils.error import DataFlowTerminatedError
|
|
31
|
+
from ..utils.file_utils import pyzmq_available
|
|
31
32
|
from ..utils.logger import LoggingRecord, logger
|
|
32
33
|
from .base import DataFlow, DataFlowReentrantGuard, ProxyDataFlow
|
|
33
34
|
from .common import RepeatedData
|
|
34
35
|
from .serialize import PickleSerializer
|
|
35
36
|
|
|
37
|
+
with try_import() as import_guard:
|
|
38
|
+
import zmq
|
|
39
|
+
|
|
36
40
|
|
|
37
41
|
@no_type_check
|
|
38
42
|
def del_weakref(x):
|
|
@@ -77,6 +81,8 @@ def _get_pipe_name(name):
|
|
|
77
81
|
|
|
78
82
|
class _ParallelMapData(ProxyDataFlow, ABC):
|
|
79
83
|
def __init__(self, df: DataFlow, buffer_size: int, strict: bool = False) -> None:
|
|
84
|
+
if not pyzmq_available():
|
|
85
|
+
raise ModuleNotFoundError("pyzmq is required for running parallel dataflows (multiprocess/multithread).")
|
|
80
86
|
super().__init__(df)
|
|
81
87
|
if buffer_size <= 0:
|
|
82
88
|
raise ValueError(f"buffer_size must be a positive number, got {buffer_size}")
|
|
@@ -284,7 +284,7 @@ class BoundingBox:
|
|
|
284
284
|
raise BoundingBoxError(
|
|
285
285
|
f"bounding box must have height and width >0. Check coords "
|
|
286
286
|
f"ulx: {self.ulx}, uly: {self.uly}, lrx: {self.lrx}, "
|
|
287
|
-
f"lry: {self.lry}."
|
|
287
|
+
f"lry: {self.lry}, absolute_coords: {self.absolute_coords}"
|
|
288
288
|
)
|
|
289
289
|
if not self.absolute_coords and not (
|
|
290
290
|
0 <= self.ulx <= 1 and 0 <= self.uly <= 1 and 0 <= self.lrx <= 1 and 0 <= self.lry <= 1
|
|
@@ -505,10 +505,10 @@ class BoundingBox:
|
|
|
505
505
|
if self.absolute_coords:
|
|
506
506
|
transformed_box = BoundingBox(
|
|
507
507
|
absolute_coords=not self.absolute_coords,
|
|
508
|
-
ulx=max(self.ulx / image_width, 0.0),
|
|
509
|
-
uly=max(self.uly / image_height, 0.0),
|
|
510
|
-
lrx=min(self.lrx / image_width, 1.0),
|
|
511
|
-
lry=min(self.lry / image_height, 1.0),
|
|
508
|
+
ulx=min(max(self.ulx / image_width, 0.0), 1.0),
|
|
509
|
+
uly=min(max(self.uly / image_height, 0.0), 1.0),
|
|
510
|
+
lrx=max(min(self.lrx / image_width, 1.0), 0.0),
|
|
511
|
+
lry=max(min(self.lry / image_height, 1.0), 0.0),
|
|
512
512
|
)
|
|
513
513
|
else:
|
|
514
514
|
transformed_box = BoundingBox(
|
|
@@ -36,7 +36,7 @@ from ..utils.logger import LoggingRecord, logger
|
|
|
36
36
|
from ..utils.settings import ObjectTypes, SummaryType, get_type
|
|
37
37
|
from ..utils.types import ImageDict, PathLikeOrStr, PixelValues
|
|
38
38
|
from .annotation import Annotation, AnnotationMap, BoundingBox, CategoryAnnotation, ImageAnnotation
|
|
39
|
-
from .box import crop_box_from_image, global_to_local_coords, intersection_box
|
|
39
|
+
from .box import BoxCoordinate, crop_box_from_image, global_to_local_coords, intersection_box
|
|
40
40
|
from .convert import as_dict, convert_b64_to_np_array, convert_np_array_to_b64, convert_pdf_bytes_to_np_array_v2
|
|
41
41
|
|
|
42
42
|
|
|
@@ -318,7 +318,7 @@ class Image:
|
|
|
318
318
|
return _Img(self.image)
|
|
319
319
|
|
|
320
320
|
@property
|
|
321
|
-
def width(self) ->
|
|
321
|
+
def width(self) -> BoxCoordinate:
|
|
322
322
|
"""
|
|
323
323
|
`width`
|
|
324
324
|
"""
|
|
@@ -327,7 +327,7 @@ class Image:
|
|
|
327
327
|
return self._bbox.width
|
|
328
328
|
|
|
329
329
|
@property
|
|
330
|
-
def height(self) ->
|
|
330
|
+
def height(self) -> BoxCoordinate:
|
|
331
331
|
"""
|
|
332
332
|
`height`
|
|
333
333
|
"""
|
|
@@ -335,7 +335,7 @@ class Image:
|
|
|
335
335
|
raise ImageError("Height not available. Call set_width_height first")
|
|
336
336
|
return self._bbox.height
|
|
337
337
|
|
|
338
|
-
def set_width_height(self, width:
|
|
338
|
+
def set_width_height(self, width: BoxCoordinate, height: BoxCoordinate) -> None:
|
|
339
339
|
"""
|
|
340
340
|
Defines bounding box of the image if not already set. Use this, if you do not want to keep the image separated
|
|
341
341
|
for memory reasons.
|
|
@@ -345,7 +345,7 @@ class Image:
|
|
|
345
345
|
height: height of image
|
|
346
346
|
"""
|
|
347
347
|
if self._bbox is None:
|
|
348
|
-
self._bbox = BoundingBox(ulx=0
|
|
348
|
+
self._bbox = BoundingBox(ulx=0, uly=0, height=height, width=width, absolute_coords=True)
|
|
349
349
|
self._self_embedding()
|
|
350
350
|
|
|
351
351
|
def set_embedding(self, image_id: str, bounding_box: BoundingBox) -> None:
|
|
@@ -428,6 +428,8 @@ class List(Layout):
|
|
|
428
428
|
A list of words order by reading order. Words with no `reading_order` will not be returned"""
|
|
429
429
|
try:
|
|
430
430
|
list_items = self.list_items
|
|
431
|
+
if not list_items:
|
|
432
|
+
return super().get_ordered_words()
|
|
431
433
|
all_words = []
|
|
432
434
|
list_items.sort(key=lambda x: x.bbox[1])
|
|
433
435
|
for list_item in list_items:
|
|
@@ -755,6 +757,8 @@ class Table(Layout):
|
|
|
755
757
|
"""
|
|
756
758
|
try:
|
|
757
759
|
cells = self.cells
|
|
760
|
+
if not cells:
|
|
761
|
+
return super().get_ordered_words()
|
|
758
762
|
all_words = []
|
|
759
763
|
cells.sort(key=lambda x: (x.ROW_NUMBER, x.COLUMN_NUMBER))
|
|
760
764
|
for cell in cells:
|
|
@@ -1054,6 +1058,8 @@ class Page(Image):
|
|
|
1054
1058
|
Returns:
|
|
1055
1059
|
A `Page` instance with all annotations as `ImageAnnotationBaseView` subclasses.
|
|
1056
1060
|
"""
|
|
1061
|
+
if isinstance(image_orig, Page):
|
|
1062
|
+
raise ImageError("Page.from_image() cannot be called on a Page instance.")
|
|
1057
1063
|
|
|
1058
1064
|
if text_container is None:
|
|
1059
1065
|
text_container = IMAGE_DEFAULTS.TEXT_CONTAINER
|
|
@@ -1310,7 +1316,7 @@ class Page(Image):
|
|
|
1310
1316
|
If `interactive=False` will return a `np.array`.
|
|
1311
1317
|
"""
|
|
1312
1318
|
|
|
1313
|
-
category_names_list: list[Union[str, None]] = []
|
|
1319
|
+
category_names_list: list[Tuple[Union[str, None], Union[str, None]]] = []
|
|
1314
1320
|
box_stack = []
|
|
1315
1321
|
cells_found = False
|
|
1316
1322
|
|
|
@@ -1323,22 +1329,23 @@ class Page(Image):
|
|
|
1323
1329
|
anns = self.get_annotation(category_names=list(debug_kwargs.keys()))
|
|
1324
1330
|
for ann in anns:
|
|
1325
1331
|
box_stack.append(self._ann_viz_bbox(ann))
|
|
1326
|
-
|
|
1332
|
+
val = str(getattr(ann, debug_kwargs[ann.category_name]))
|
|
1333
|
+
category_names_list.append((val, val))
|
|
1327
1334
|
|
|
1328
1335
|
if show_layouts and not debug_kwargs:
|
|
1329
1336
|
for item in self.layouts:
|
|
1330
1337
|
box_stack.append(self._ann_viz_bbox(item))
|
|
1331
|
-
category_names_list.append(item.category_name.value)
|
|
1338
|
+
category_names_list.append((item.category_name.value, item.category_name.value))
|
|
1332
1339
|
|
|
1333
1340
|
if show_figures and not debug_kwargs:
|
|
1334
1341
|
for item in self.figures:
|
|
1335
1342
|
box_stack.append(self._ann_viz_bbox(item))
|
|
1336
|
-
category_names_list.append(item.category_name.value)
|
|
1343
|
+
category_names_list.append((item.category_name.value, item.category_name.value))
|
|
1337
1344
|
|
|
1338
1345
|
if show_tables and not debug_kwargs:
|
|
1339
1346
|
for table in self.tables:
|
|
1340
1347
|
box_stack.append(self._ann_viz_bbox(table))
|
|
1341
|
-
category_names_list.append(LayoutType.TABLE.value)
|
|
1348
|
+
category_names_list.append((LayoutType.TABLE.value, LayoutType.TABLE.value))
|
|
1342
1349
|
if show_cells:
|
|
1343
1350
|
for cell in table.cells:
|
|
1344
1351
|
if cell.category_name in {
|
|
@@ -1347,21 +1354,21 @@ class Page(Image):
|
|
|
1347
1354
|
}:
|
|
1348
1355
|
cells_found = True
|
|
1349
1356
|
box_stack.append(self._ann_viz_bbox(cell))
|
|
1350
|
-
category_names_list.append(None)
|
|
1357
|
+
category_names_list.append((None, cell.category_name.value))
|
|
1351
1358
|
if show_table_structure:
|
|
1352
1359
|
rows = table.rows
|
|
1353
1360
|
cols = table.columns
|
|
1354
1361
|
for row in rows:
|
|
1355
1362
|
box_stack.append(self._ann_viz_bbox(row))
|
|
1356
|
-
category_names_list.append(None)
|
|
1363
|
+
category_names_list.append((None, row.category_name.value))
|
|
1357
1364
|
for col in cols:
|
|
1358
1365
|
box_stack.append(self._ann_viz_bbox(col))
|
|
1359
|
-
category_names_list.append(None)
|
|
1366
|
+
category_names_list.append((None, col.category_name.value))
|
|
1360
1367
|
|
|
1361
1368
|
if show_cells and not cells_found and not debug_kwargs:
|
|
1362
1369
|
for ann in self.get_annotation(category_names=[LayoutType.CELL, CellType.SPANNING]):
|
|
1363
1370
|
box_stack.append(self._ann_viz_bbox(ann))
|
|
1364
|
-
category_names_list.append(None)
|
|
1371
|
+
category_names_list.append((None, ann.category_name.value))
|
|
1365
1372
|
|
|
1366
1373
|
if show_words and not debug_kwargs:
|
|
1367
1374
|
all_words = []
|
|
@@ -1379,22 +1386,36 @@ class Page(Image):
|
|
|
1379
1386
|
for word in all_words:
|
|
1380
1387
|
box_stack.append(self._ann_viz_bbox(word))
|
|
1381
1388
|
if show_token_class:
|
|
1382
|
-
category_names_list.append(
|
|
1389
|
+
category_names_list.append(
|
|
1390
|
+
(word.token_class.value, word.token_class.value)
|
|
1391
|
+
if word.token_class is not None
|
|
1392
|
+
else (None, None)
|
|
1393
|
+
)
|
|
1383
1394
|
else:
|
|
1384
|
-
category_names_list.append(
|
|
1395
|
+
category_names_list.append(
|
|
1396
|
+
(word.token_tag.value, word.token_tag.value) if word.token_tag is not None else (None, None)
|
|
1397
|
+
)
|
|
1385
1398
|
else:
|
|
1386
1399
|
for word in all_words:
|
|
1387
1400
|
if word.token_class is not None and word.token_class != TokenClasses.OTHER:
|
|
1388
1401
|
box_stack.append(self._ann_viz_bbox(word))
|
|
1389
1402
|
if show_token_class:
|
|
1390
|
-
category_names_list.append(
|
|
1403
|
+
category_names_list.append(
|
|
1404
|
+
(word.token_class.value, word.token_class.value)
|
|
1405
|
+
if word.token_class is not None
|
|
1406
|
+
else (None, None)
|
|
1407
|
+
)
|
|
1391
1408
|
else:
|
|
1392
|
-
category_names_list.append(
|
|
1409
|
+
category_names_list.append(
|
|
1410
|
+
(word.token_tag.value, word.token_tag.value)
|
|
1411
|
+
if word.token_tag is not None
|
|
1412
|
+
else (None, None)
|
|
1413
|
+
)
|
|
1393
1414
|
|
|
1394
1415
|
if show_residual_layouts and not debug_kwargs:
|
|
1395
1416
|
for item in self.residual_layouts:
|
|
1396
1417
|
box_stack.append(item.bbox)
|
|
1397
|
-
category_names_list.append(item.category_name.value)
|
|
1418
|
+
category_names_list.append((item.category_name.value, item.category_name.value))
|
|
1398
1419
|
|
|
1399
1420
|
if self.image is not None:
|
|
1400
1421
|
scale_fx = scaled_width / self.width
|
|
@@ -275,6 +275,7 @@ class CocoMetric(MetricBase):
|
|
|
275
275
|
get the ultimate F1-score.
|
|
276
276
|
f1_iou: Use with `f1_score=True` and reset the f1 iou threshold
|
|
277
277
|
per_category: Whether to calculate metrics per category
|
|
278
|
+
per_category: If set to True, f1 score will be returned by each category.
|
|
278
279
|
"""
|
|
279
280
|
if max_detections is not None:
|
|
280
281
|
assert len(max_detections) == 3, max_detections
|
|
@@ -263,7 +263,7 @@ class PredictorBase(ABC):
|
|
|
263
263
|
requirements = cls.get_requirements()
|
|
264
264
|
name = cls.__name__ if hasattr(cls, "__name__") else cls.__class__.__name__
|
|
265
265
|
if not all(requirement[1] for requirement in requirements):
|
|
266
|
-
raise
|
|
266
|
+
raise ModuleNotFoundError(
|
|
267
267
|
"\n".join(
|
|
268
268
|
[f"{name} has the following dependencies:"]
|
|
269
269
|
+ [requirement[2] for requirement in requirements if not requirement[1]]
|
|
@@ -334,6 +334,11 @@ class DetectionResult:
|
|
|
334
334
|
block: block number. For reading order from some ocr predictors
|
|
335
335
|
line: line number. For reading order from some ocr predictors
|
|
336
336
|
uuid: uuid. For assigning detection result (e.g. text to image annotations)
|
|
337
|
+
relationships: A dictionary of relationships. Each key is a relationship type and each value is a list of
|
|
338
|
+
uuids of the related annotations.
|
|
339
|
+
angle: angle of rotation in degrees. Only used for text detection.
|
|
340
|
+
image_width: image width
|
|
341
|
+
image_height: image height
|
|
337
342
|
"""
|
|
338
343
|
|
|
339
344
|
box: Optional[list[float]] = None
|
|
@@ -348,6 +353,8 @@ class DetectionResult:
|
|
|
348
353
|
uuid: Optional[str] = None
|
|
349
354
|
relationships: Optional[dict[str, Any]] = None
|
|
350
355
|
angle: Optional[float] = None
|
|
356
|
+
image_width: Optional[Union[int, float]] = None
|
|
357
|
+
image_height: Optional[Union[int, float]] = None
|
|
351
358
|
|
|
352
359
|
|
|
353
360
|
class ObjectDetector(PredictorBase, ABC):
|
|
@@ -24,9 +24,10 @@ from __future__ import annotations
|
|
|
24
24
|
import os
|
|
25
25
|
from abc import ABC
|
|
26
26
|
from pathlib import Path
|
|
27
|
-
from typing import Any, Literal, Mapping, Optional, Union
|
|
27
|
+
from typing import Any, Literal, Mapping, Optional, Sequence, Union
|
|
28
28
|
from zipfile import ZipFile
|
|
29
29
|
|
|
30
|
+
import numpy as np
|
|
30
31
|
from lazy_imports import try_import
|
|
31
32
|
|
|
32
33
|
from ..utils.env_info import ENV_VARS_TRUE
|
|
@@ -39,6 +40,7 @@ from ..utils.file_utils import (
|
|
|
39
40
|
)
|
|
40
41
|
from ..utils.fs import load_json
|
|
41
42
|
from ..utils.settings import LayoutType, ObjectTypes, PageType, TypeOrStr
|
|
43
|
+
from ..utils.transform import RotationTransform
|
|
42
44
|
from ..utils.types import PathLikeOrStr, PixelValues, Requirement
|
|
43
45
|
from ..utils.viz import viz_handler
|
|
44
46
|
from .base import DetectionResult, ImageTransformer, ModelCategories, ObjectDetector, TextRecognizer
|
|
@@ -558,12 +560,13 @@ class DocTrRotationTransformer(ImageTransformer):
|
|
|
558
560
|
"""
|
|
559
561
|
Args:
|
|
560
562
|
number_contours: the number of contours used for the orientation estimation
|
|
561
|
-
ratio_threshold_for_lines: this is the ratio w/h used to
|
|
563
|
+
ratio_threshold_for_lines: this is the ratio w/h used to discriminate lines
|
|
562
564
|
"""
|
|
563
565
|
self.number_contours = number_contours
|
|
564
566
|
self.ratio_threshold_for_lines = ratio_threshold_for_lines
|
|
565
567
|
self.name = "doctr_rotation_transformer"
|
|
566
568
|
self.model_id = self.get_model_id()
|
|
569
|
+
self.rotator = RotationTransform(360)
|
|
567
570
|
|
|
568
571
|
def transform_image(self, np_img: PixelValues, specification: DetectionResult) -> PixelValues:
|
|
569
572
|
"""
|
|
@@ -579,6 +582,19 @@ class DocTrRotationTransformer(ImageTransformer):
|
|
|
579
582
|
"""
|
|
580
583
|
return viz_handler.rotate_image(np_img, specification.angle) # type: ignore
|
|
581
584
|
|
|
585
|
+
def transform_coords(self, detect_results: Sequence[DetectionResult]) -> Sequence[DetectionResult]:
|
|
586
|
+
if detect_results:
|
|
587
|
+
if detect_results[0].angle:
|
|
588
|
+
self.rotator.set_angle(detect_results[0].angle) # type: ignore
|
|
589
|
+
self.rotator.set_image_width(detect_results[0].image_width) # type: ignore
|
|
590
|
+
self.rotator.set_image_height(detect_results[0].image_height) # type: ignore
|
|
591
|
+
transformed_coords = self.rotator.apply_coords(
|
|
592
|
+
np.asarray([detect_result.box for detect_result in detect_results], dtype=float)
|
|
593
|
+
)
|
|
594
|
+
for idx, detect_result in enumerate(detect_results):
|
|
595
|
+
detect_result.box = transformed_coords[idx, :].tolist()
|
|
596
|
+
return detect_results
|
|
597
|
+
|
|
582
598
|
def predict(self, np_img: PixelValues) -> DetectionResult:
|
|
583
599
|
angle = estimate_orientation(
|
|
584
600
|
np_img, n_ct=self.number_contours, ratio_threshold_for_lines=self.ratio_threshold_for_lines
|
|
@@ -1024,12 +1024,9 @@ class HFLayoutLmv2SequenceClassifier(HFLayoutLmSequenceClassifierBase):
|
|
|
1024
1024
|
else:
|
|
1025
1025
|
raise ValueError(f"images must be list but is {type(images)}")
|
|
1026
1026
|
|
|
1027
|
-
result = predict_sequence_classes_from_layoutlm(
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
boxes,
|
|
1031
|
-
self.model,
|
|
1032
|
-
images)
|
|
1027
|
+
result = predict_sequence_classes_from_layoutlm(
|
|
1028
|
+
input_ids, attention_mask, token_type_ids, boxes, self.model, images
|
|
1029
|
+
)
|
|
1033
1030
|
|
|
1034
1031
|
result.class_id += 1
|
|
1035
1032
|
result.class_name = self.categories.categories[result.class_id]
|
|
@@ -1123,12 +1120,9 @@ class HFLayoutLmv3SequenceClassifier(HFLayoutLmSequenceClassifierBase):
|
|
|
1123
1120
|
else:
|
|
1124
1121
|
raise ValueError(f"images must be list but is {type(images)}")
|
|
1125
1122
|
|
|
1126
|
-
result = predict_sequence_classes_from_layoutlm(
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
boxes,
|
|
1130
|
-
self.model,
|
|
1131
|
-
images)
|
|
1123
|
+
result = predict_sequence_classes_from_layoutlm(
|
|
1124
|
+
input_ids, attention_mask, token_type_ids, boxes, self.model, images
|
|
1125
|
+
)
|
|
1132
1126
|
|
|
1133
1127
|
result.class_id += 1
|
|
1134
1128
|
result.class_name = self.categories.categories[result.class_id]
|
|
@@ -28,8 +28,9 @@ from errno import ENOENT
|
|
|
28
28
|
from itertools import groupby
|
|
29
29
|
from os import environ, fspath
|
|
30
30
|
from pathlib import Path
|
|
31
|
-
from typing import Any, Mapping, Optional, Union
|
|
31
|
+
from typing import Any, Mapping, Optional, Sequence, Union
|
|
32
32
|
|
|
33
|
+
import numpy as np
|
|
33
34
|
from packaging.version import InvalidVersion, Version, parse
|
|
34
35
|
|
|
35
36
|
from ..utils.context import save_tmp_file, timeout_manager
|
|
@@ -37,6 +38,7 @@ from ..utils.error import DependencyError, TesseractError
|
|
|
37
38
|
from ..utils.file_utils import _TESS_PATH, get_tesseract_requirement
|
|
38
39
|
from ..utils.metacfg import config_to_cli_str, set_config_by_yaml
|
|
39
40
|
from ..utils.settings import LayoutType, ObjectTypes, PageType
|
|
41
|
+
from ..utils.transform import RotationTransform
|
|
40
42
|
from ..utils.types import PathLikeOrStr, PixelValues, Requirement
|
|
41
43
|
from ..utils.viz import viz_handler
|
|
42
44
|
from .base import DetectionResult, ImageTransformer, ModelCategories, ObjectDetector
|
|
@@ -450,6 +452,7 @@ class TesseractRotationTransformer(ImageTransformer):
|
|
|
450
452
|
self.name = fspath(_TESS_PATH) + "-rotation"
|
|
451
453
|
self.categories = ModelCategories(init_categories={1: PageType.ANGLE})
|
|
452
454
|
self.model_id = self.get_model_id()
|
|
455
|
+
self.rotator = RotationTransform(360)
|
|
453
456
|
|
|
454
457
|
def transform_image(self, np_img: PixelValues, specification: DetectionResult) -> PixelValues:
|
|
455
458
|
"""
|
|
@@ -465,6 +468,19 @@ class TesseractRotationTransformer(ImageTransformer):
|
|
|
465
468
|
"""
|
|
466
469
|
return viz_handler.rotate_image(np_img, specification.angle) # type: ignore
|
|
467
470
|
|
|
471
|
+
def transform_coords(self, detect_results: Sequence[DetectionResult]) -> Sequence[DetectionResult]:
|
|
472
|
+
if detect_results:
|
|
473
|
+
if detect_results[0].angle:
|
|
474
|
+
self.rotator.set_angle(detect_results[0].angle) # type: ignore
|
|
475
|
+
self.rotator.set_image_width(detect_results[0].image_width) # type: ignore
|
|
476
|
+
self.rotator.set_image_height(detect_results[0].image_height) # type: ignore
|
|
477
|
+
transformed_coords = self.rotator.apply_coords(
|
|
478
|
+
np.asarray([detect_result.box for detect_result in detect_results], dtype=float)
|
|
479
|
+
)
|
|
480
|
+
for idx, detect_result in enumerate(detect_results):
|
|
481
|
+
detect_result.box = transformed_coords[idx, :].tolist()
|
|
482
|
+
return detect_results
|
|
483
|
+
|
|
468
484
|
def predict(self, np_img: PixelValues) -> DetectionResult:
|
|
469
485
|
"""
|
|
470
486
|
Determines the angle of the rotated image. It can only handle angles that are multiples of 90 degrees.
|
|
@@ -228,8 +228,8 @@ class OrderGenerator:
|
|
|
228
228
|
columns: list[BoundingBox] = []
|
|
229
229
|
anns.sort(
|
|
230
230
|
key=lambda x: (
|
|
231
|
-
x.
|
|
232
|
-
x.
|
|
231
|
+
x.get_bounding_box(image_id).transform(image_width, image_height).cy,
|
|
232
|
+
x.get_bounding_box(image_id).transform(image_width, image_height).cx,
|
|
233
233
|
)
|
|
234
234
|
)
|
|
235
235
|
for ann in anns:
|
|
@@ -309,7 +309,9 @@ class OrderGenerator:
|
|
|
309
309
|
filtered_blocks: Sequence[tuple[int, str]]
|
|
310
310
|
for idx in range(max_block_number + 1):
|
|
311
311
|
filtered_blocks = list(filter(lambda x: x[0] == idx, blocks)) # type: ignore # pylint: disable=W0640
|
|
312
|
-
sorted_blocks.extend(
|
|
312
|
+
sorted_blocks.extend(
|
|
313
|
+
self._sort_anns_grouped_by_blocks(filtered_blocks, anns, image_width, image_height, image_id)
|
|
314
|
+
)
|
|
313
315
|
reading_blocks = [(idx + 1, block[1]) for idx, block in enumerate(sorted_blocks)]
|
|
314
316
|
|
|
315
317
|
if logger.isEnabledFor(DEBUG):
|
|
@@ -346,7 +348,11 @@ class OrderGenerator:
|
|
|
346
348
|
|
|
347
349
|
@staticmethod
|
|
348
350
|
def _sort_anns_grouped_by_blocks(
|
|
349
|
-
block: Sequence[tuple[int, str]],
|
|
351
|
+
block: Sequence[tuple[int, str]],
|
|
352
|
+
anns: Sequence[ImageAnnotation],
|
|
353
|
+
image_width: float,
|
|
354
|
+
image_height: float,
|
|
355
|
+
image_id: Optional[str] = None,
|
|
350
356
|
) -> list[tuple[int, str]]:
|
|
351
357
|
if not block:
|
|
352
358
|
return []
|
|
@@ -356,8 +362,8 @@ class OrderGenerator:
|
|
|
356
362
|
block_anns = [ann for ann in anns if ann.annotation_id in ann_ids]
|
|
357
363
|
block_anns.sort(
|
|
358
364
|
key=lambda x: (
|
|
359
|
-
round(x.
|
|
360
|
-
round(x.
|
|
365
|
+
round(x.get_bounding_box(image_id).transform(image_width, image_height).uly, 2),
|
|
366
|
+
round(x.get_bounding_box(image_id).transform(image_width, image_height).ulx, 2),
|
|
361
367
|
)
|
|
362
368
|
)
|
|
363
369
|
return [(block_number, ann.annotation_id) for ann in block_anns]
|