deepdoctection 0.42.1__py3-none-any.whl → 0.43.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.
Potentially problematic release.
This version of deepdoctection might be problematic. Click here for more details.
- deepdoctection/__init__.py +4 -2
- deepdoctection/analyzer/__init__.py +2 -1
- deepdoctection/analyzer/config.py +919 -0
- deepdoctection/analyzer/dd.py +36 -62
- deepdoctection/analyzer/factory.py +311 -141
- deepdoctection/configs/conf_dd_one.yaml +100 -44
- deepdoctection/configs/profiles.jsonl +32 -0
- deepdoctection/dataflow/__init__.py +9 -6
- deepdoctection/dataflow/base.py +33 -15
- deepdoctection/dataflow/common.py +96 -75
- deepdoctection/dataflow/custom.py +36 -29
- deepdoctection/dataflow/custom_serialize.py +135 -91
- deepdoctection/dataflow/parallel_map.py +33 -31
- deepdoctection/dataflow/serialize.py +15 -10
- deepdoctection/dataflow/stats.py +41 -28
- deepdoctection/datapoint/__init__.py +4 -6
- deepdoctection/datapoint/annotation.py +104 -66
- deepdoctection/datapoint/box.py +190 -130
- deepdoctection/datapoint/convert.py +66 -39
- deepdoctection/datapoint/image.py +151 -95
- deepdoctection/datapoint/view.py +383 -236
- deepdoctection/datasets/__init__.py +2 -6
- deepdoctection/datasets/adapter.py +11 -11
- deepdoctection/datasets/base.py +118 -81
- deepdoctection/datasets/dataflow_builder.py +18 -12
- deepdoctection/datasets/info.py +76 -57
- deepdoctection/datasets/instances/__init__.py +6 -2
- deepdoctection/datasets/instances/doclaynet.py +17 -14
- deepdoctection/datasets/instances/fintabnet.py +16 -22
- deepdoctection/datasets/instances/funsd.py +11 -6
- deepdoctection/datasets/instances/iiitar13k.py +9 -9
- deepdoctection/datasets/instances/layouttest.py +9 -9
- deepdoctection/datasets/instances/publaynet.py +9 -9
- deepdoctection/datasets/instances/pubtables1m.py +13 -13
- deepdoctection/datasets/instances/pubtabnet.py +13 -15
- deepdoctection/datasets/instances/rvlcdip.py +8 -8
- deepdoctection/datasets/instances/xfund.py +11 -9
- deepdoctection/datasets/registry.py +18 -11
- deepdoctection/datasets/save.py +12 -11
- deepdoctection/eval/__init__.py +3 -2
- deepdoctection/eval/accmetric.py +72 -52
- deepdoctection/eval/base.py +29 -10
- deepdoctection/eval/cocometric.py +14 -12
- deepdoctection/eval/eval.py +56 -41
- deepdoctection/eval/registry.py +6 -3
- deepdoctection/eval/tedsmetric.py +24 -9
- deepdoctection/eval/tp_eval_callback.py +13 -12
- deepdoctection/extern/__init__.py +1 -1
- deepdoctection/extern/base.py +176 -97
- deepdoctection/extern/d2detect.py +127 -92
- deepdoctection/extern/deskew.py +19 -10
- deepdoctection/extern/doctrocr.py +162 -108
- deepdoctection/extern/fastlang.py +25 -17
- deepdoctection/extern/hfdetr.py +137 -60
- deepdoctection/extern/hflayoutlm.py +329 -248
- deepdoctection/extern/hflm.py +67 -33
- deepdoctection/extern/model.py +108 -762
- deepdoctection/extern/pdftext.py +37 -12
- deepdoctection/extern/pt/nms.py +15 -1
- deepdoctection/extern/pt/ptutils.py +13 -9
- deepdoctection/extern/tessocr.py +87 -54
- deepdoctection/extern/texocr.py +29 -14
- deepdoctection/extern/tp/tfutils.py +36 -8
- deepdoctection/extern/tp/tpcompat.py +54 -16
- deepdoctection/extern/tp/tpfrcnn/config/config.py +20 -4
- deepdoctection/extern/tpdetect.py +4 -2
- deepdoctection/mapper/__init__.py +1 -1
- deepdoctection/mapper/cats.py +117 -76
- deepdoctection/mapper/cocostruct.py +35 -17
- deepdoctection/mapper/d2struct.py +56 -29
- deepdoctection/mapper/hfstruct.py +32 -19
- deepdoctection/mapper/laylmstruct.py +221 -185
- deepdoctection/mapper/maputils.py +71 -35
- deepdoctection/mapper/match.py +76 -62
- deepdoctection/mapper/misc.py +68 -44
- deepdoctection/mapper/pascalstruct.py +13 -12
- deepdoctection/mapper/prodigystruct.py +33 -19
- deepdoctection/mapper/pubstruct.py +42 -32
- deepdoctection/mapper/tpstruct.py +39 -19
- deepdoctection/mapper/xfundstruct.py +20 -13
- deepdoctection/pipe/__init__.py +1 -2
- deepdoctection/pipe/anngen.py +104 -62
- deepdoctection/pipe/base.py +226 -107
- deepdoctection/pipe/common.py +206 -123
- deepdoctection/pipe/concurrency.py +74 -47
- deepdoctection/pipe/doctectionpipe.py +108 -47
- deepdoctection/pipe/language.py +41 -24
- deepdoctection/pipe/layout.py +45 -18
- deepdoctection/pipe/lm.py +146 -78
- deepdoctection/pipe/order.py +205 -119
- deepdoctection/pipe/refine.py +111 -63
- deepdoctection/pipe/registry.py +1 -1
- deepdoctection/pipe/segment.py +213 -142
- deepdoctection/pipe/sub_layout.py +76 -46
- deepdoctection/pipe/text.py +52 -33
- deepdoctection/pipe/transform.py +8 -6
- deepdoctection/train/d2_frcnn_train.py +87 -69
- deepdoctection/train/hf_detr_train.py +72 -40
- deepdoctection/train/hf_layoutlm_train.py +85 -46
- deepdoctection/train/tp_frcnn_train.py +56 -28
- deepdoctection/utils/concurrency.py +59 -16
- deepdoctection/utils/context.py +40 -19
- deepdoctection/utils/develop.py +26 -17
- deepdoctection/utils/env_info.py +86 -37
- deepdoctection/utils/error.py +16 -10
- deepdoctection/utils/file_utils.py +246 -71
- deepdoctection/utils/fs.py +162 -43
- deepdoctection/utils/identifier.py +29 -16
- deepdoctection/utils/logger.py +49 -32
- deepdoctection/utils/metacfg.py +83 -21
- deepdoctection/utils/pdf_utils.py +119 -62
- deepdoctection/utils/settings.py +24 -10
- deepdoctection/utils/tqdm.py +10 -5
- deepdoctection/utils/transform.py +182 -46
- deepdoctection/utils/utils.py +61 -28
- deepdoctection/utils/viz.py +150 -104
- deepdoctection-0.43.1.dist-info/METADATA +376 -0
- deepdoctection-0.43.1.dist-info/RECORD +149 -0
- deepdoctection/analyzer/_config.py +0 -146
- deepdoctection-0.42.1.dist-info/METADATA +0 -431
- deepdoctection-0.42.1.dist-info/RECORD +0 -148
- {deepdoctection-0.42.1.dist-info → deepdoctection-0.43.1.dist-info}/WHEEL +0 -0
- {deepdoctection-0.42.1.dist-info → deepdoctection-0.43.1.dist-info}/licenses/LICENSE +0 -0
- {deepdoctection-0.42.1.dist-info → deepdoctection-0.43.1.dist-info}/top_level.txt +0 -0
deepdoctection/pipe/segment.py
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
"""
|
|
19
19
|
Module for pipeline component of table segmentation. Uses row/column detector and infers segmentations by using
|
|
20
|
-
ious
|
|
20
|
+
`ious`/`ioas` of rows and columns.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
from __future__ import annotations
|
|
@@ -45,7 +45,14 @@ __all__ = ["TableSegmentationService", "SegmentationResult", "PubtablesSegmentat
|
|
|
45
45
|
@dataclass
|
|
46
46
|
class SegmentationResult:
|
|
47
47
|
"""
|
|
48
|
-
|
|
48
|
+
Mutable storage for segmentation results.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
annotation_id: The annotation ID.
|
|
52
|
+
row_num: The row number.
|
|
53
|
+
col_num: The column number.
|
|
54
|
+
rs: The row span.
|
|
55
|
+
cs: The column span.
|
|
49
56
|
"""
|
|
50
57
|
|
|
51
58
|
annotation_id: str
|
|
@@ -72,17 +79,20 @@ def choose_items_by_iou(
|
|
|
72
79
|
reference_item_proposals: Optional[list[ImageAnnotation]] = None,
|
|
73
80
|
) -> Image:
|
|
74
81
|
"""
|
|
75
|
-
Deactivate image annotations that have ious with each other above some threshold. It will deactivate an annotation
|
|
76
|
-
that has iou above some threshold with another annotation and that has a lesser score.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
Deactivate image annotations that have `ious` with each other above some threshold. It will deactivate an annotation
|
|
83
|
+
that has `iou` above some threshold with another annotation and that has a lesser score.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
dp: `image`.
|
|
87
|
+
item_proposals: Annotations to choose from. If `reference_item_proposals` is `None` it will compare items with
|
|
88
|
+
each other.
|
|
89
|
+
iou_threshold: `iou_threshold`.
|
|
90
|
+
above_threshold: Whether to deactivate items above the threshold.
|
|
91
|
+
reference_item_proposals: Annotations as reference. If provided, it will compare `item_proposals` with
|
|
92
|
+
`reference_item_proposals`.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
The updated `Image`.
|
|
86
96
|
"""
|
|
87
97
|
if len(item_proposals) <= 1: # we want to ensure to have at least one element.
|
|
88
98
|
return dp
|
|
@@ -133,15 +143,17 @@ def stretch_item_per_table(
|
|
|
133
143
|
lines across the entire width of the table, lines are stretched from the left to the right edge of the table if the
|
|
134
144
|
y coordinates remain the same. Columns between the top and bottom of the table can be stretched in an analogous way.
|
|
135
145
|
|
|
136
|
-
:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"""
|
|
146
|
+
Args:
|
|
147
|
+
dp: `Image`.
|
|
148
|
+
table: Table `ImageAnnotation`.
|
|
149
|
+
row_name: Item name for horizontal stretching.
|
|
150
|
+
col_name: Item name for vertical stretching.
|
|
151
|
+
remove_iou_threshold_rows: `iou` threshold for removing overlapping rows.
|
|
152
|
+
remove_iou_threshold_cols: `iou` threshold for removing overlapping columns.
|
|
144
153
|
|
|
154
|
+
Returns:
|
|
155
|
+
The updated `Image`.
|
|
156
|
+
"""
|
|
145
157
|
item_ann_ids = table.get_relationship(Relationships.CHILD)
|
|
146
158
|
|
|
147
159
|
rows = dp.get_annotation(category_names=row_name, annotation_ids=item_ann_ids)
|
|
@@ -331,18 +343,20 @@ def tile_tables_with_items_per_table(
|
|
|
331
343
|
coordinate axes. The first item is stretched to the top or right-hand edge of the table. The next item down or to
|
|
332
344
|
the right is stretched to the lower or right edge of the previous item.
|
|
333
345
|
|
|
334
|
-
:
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
+
Args:
|
|
347
|
+
dp: `Image`.
|
|
348
|
+
table: Table.
|
|
349
|
+
item_name: `names.C.ROW` or `names.C.COL`.
|
|
350
|
+
stretch_rule: Tiling can be achieved by two different stretching rules for rows and columns.
|
|
351
|
+
- `left`: The upper horizontal edge of a row will be shifted up to the lower horizontal edge of the upper
|
|
352
|
+
neighboring row. Similarly, the left sided vertical edge of a column will be shifted towards the
|
|
353
|
+
right sided vertical edge of the left sided neighboring column.
|
|
354
|
+
- `equal`: Upper and lower horizontal edge of rows will be shifted to the middle of the gap of two
|
|
355
|
+
neighboring rows. Similarly, left and right sided vertical edge of a column will be shifted to
|
|
356
|
+
the middle of the gap of two neighboring columns.
|
|
357
|
+
|
|
358
|
+
Returns:
|
|
359
|
+
The updated `Image`.
|
|
346
360
|
"""
|
|
347
361
|
|
|
348
362
|
item_ann_ids = table.get_relationship(Relationships.CHILD)
|
|
@@ -371,15 +385,18 @@ def stretch_items(
|
|
|
371
385
|
remove_iou_threshold_cols: float,
|
|
372
386
|
) -> Image:
|
|
373
387
|
"""
|
|
374
|
-
Stretch rows and columns from item detector to full table length and width. See `stretch_item_per_table
|
|
375
|
-
|
|
376
|
-
:
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
388
|
+
Stretch rows and columns from item detector to full table length and width. See `stretch_item_per_table`.
|
|
389
|
+
|
|
390
|
+
Args:
|
|
391
|
+
dp: `Image`.
|
|
392
|
+
table_name: Category name for a table category annotation.
|
|
393
|
+
row_name: Category name for row category annotation.
|
|
394
|
+
col_name: Category name for column category annotation.
|
|
395
|
+
remove_iou_threshold_rows: `iou` threshold for removing overlapping rows.
|
|
396
|
+
remove_iou_threshold_cols: `iou` threshold for removing overlapping columns.
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
An `Image`.
|
|
383
400
|
"""
|
|
384
401
|
table_anns = dp.get_annotation(category_names=table_name)
|
|
385
402
|
|
|
@@ -394,8 +411,11 @@ def _default_segment_table(cells: list[ImageAnnotation]) -> list[SegmentationRes
|
|
|
394
411
|
Error segmentation handling when segmentation goes wrong. It will generate a default segmentation, e.g. no real
|
|
395
412
|
segmentation.
|
|
396
413
|
|
|
397
|
-
:
|
|
398
|
-
|
|
414
|
+
Args:
|
|
415
|
+
cells: List of all cells of one table.
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
List of `SegmentationResult`.
|
|
399
419
|
"""
|
|
400
420
|
raw_table_segments = []
|
|
401
421
|
for cell in cells:
|
|
@@ -415,22 +435,25 @@ def segment_table(
|
|
|
415
435
|
threshold_cols: float,
|
|
416
436
|
) -> list[SegmentationResult]:
|
|
417
437
|
"""
|
|
418
|
-
Segments a table,i.e. produces for each cell a SegmentationResult
|
|
419
|
-
be predicted by an appropriate detector.
|
|
420
|
-
with all rows. All ious with rows above iou_threshold_rows will induce the cell to have that row number. As
|
|
421
|
-
might be several rows, the row number of the cell will be the smallest of the number of all intersected rows.
|
|
422
|
-
row span will be equal the number of all rows with iou above the iou threshold.
|
|
423
|
-
|
|
424
|
-
:
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
438
|
+
Segments a table, i.e. produces for each cell a `SegmentationResult`. It uses numbered rows and columns that have
|
|
439
|
+
to be predicted by an appropriate detector. For calculating row and row spans it first infers the `iou` of a cell
|
|
440
|
+
with all rows. All `ious` with rows above `iou_threshold_rows` will induce the cell to have that row number. As
|
|
441
|
+
there might be several rows, the row number of the cell will be the smallest of the number of all intersected rows.
|
|
442
|
+
The row span will be equal to the number of all rows with `iou` above the `iou` threshold.
|
|
443
|
+
|
|
444
|
+
Args:
|
|
445
|
+
dp: A datapoint.
|
|
446
|
+
table: The table as `ImageAnnotation`.
|
|
447
|
+
item_names: A list of item names (e.g. `row` and `column`).
|
|
448
|
+
cell_names: A list of cell names (e.g. `cell`).
|
|
449
|
+
segment_rule: `iou` or `ioa`.
|
|
450
|
+
threshold_rows: The `iou`/`ioa` threshold of a cell with a row in order to conclude that the cell belongs to
|
|
451
|
+
the row.
|
|
452
|
+
threshold_cols: The `iou`/`ioa` threshold of a cell with a column in order to conclude that the cell belongs to
|
|
453
|
+
the column.
|
|
454
|
+
|
|
455
|
+
Returns:
|
|
456
|
+
A list of `SegmentationResult` for each cell.
|
|
434
457
|
"""
|
|
435
458
|
|
|
436
459
|
child_ann_ids = table.get_relationship(Relationships.CHILD)
|
|
@@ -507,11 +530,14 @@ def create_intersection_cells(
|
|
|
507
530
|
Given rows and columns with row- and column number sub categories, create a list of `DetectionResult` and
|
|
508
531
|
`SegmentationResult` as intersection of all their intersection rectangles.
|
|
509
532
|
|
|
510
|
-
:
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
533
|
+
Args:
|
|
534
|
+
rows: List of rows.
|
|
535
|
+
cols: List of columns.
|
|
536
|
+
table_annotation_id: Annotation ID of underlying table `ImageAnnotation`.
|
|
537
|
+
sub_item_names: `ObjectTypes` for row-/column number.
|
|
538
|
+
|
|
539
|
+
Returns:
|
|
540
|
+
Pair of lists of `DetectionResult` and `SegmentationResult`.
|
|
515
541
|
"""
|
|
516
542
|
boxes_rows = [row.get_bounding_box(table_annotation_id) for row in rows]
|
|
517
543
|
boxes_cols = [col.get_bounding_box(table_annotation_id) for col in cols]
|
|
@@ -559,16 +585,19 @@ def header_cell_to_item_detect_result(
|
|
|
559
585
|
threshold: float,
|
|
560
586
|
) -> list[ItemHeaderResult]:
|
|
561
587
|
"""
|
|
562
|
-
Match header cells to items (rows or columns) based on intersection-over-union (iou) or
|
|
563
|
-
and return a list of ItemHeaderResult
|
|
564
|
-
|
|
565
|
-
:
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
588
|
+
Match header cells to items (rows or columns) based on intersection-over-union (`iou`) or
|
|
589
|
+
intersection-over-area (`ioa`) and return a list of `ItemHeaderResult`.
|
|
590
|
+
|
|
591
|
+
Args:
|
|
592
|
+
dp: The image containing the table and items.
|
|
593
|
+
table: The table `ImageAnnotation`.
|
|
594
|
+
item_name: The type of items (e.g., rows or columns) to match with header cells.
|
|
595
|
+
item_header_name: The type of header cells to match with items.
|
|
596
|
+
segment_rule: The rule to use for matching, either `iou` or `ioa`.
|
|
597
|
+
threshold: The `iou`/`ioa` threshold for matching header cells with items.
|
|
598
|
+
|
|
599
|
+
Returns:
|
|
600
|
+
A list of `ItemHeaderResult` containing the matched header cells.
|
|
572
601
|
"""
|
|
573
602
|
child_ann_ids = table.get_relationship(Relationships.CHILD)
|
|
574
603
|
item_index, _, items, _ = match_anns_by_intersection(
|
|
@@ -606,16 +635,19 @@ def segment_pubtables(
|
|
|
606
635
|
All simple cells that are covered by a spanning cell as well in the table position (double allocation) are then
|
|
607
636
|
replaced by the spanning cell and deactivated.
|
|
608
637
|
|
|
609
|
-
:
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
638
|
+
Args:
|
|
639
|
+
dp: `Image`.
|
|
640
|
+
table: Table `ImageAnnotation`.
|
|
641
|
+
item_names: A list of item names (e.g. `row` and `column`).
|
|
642
|
+
spanning_cell_names: A list of spanning cell names (e.g. `projected_row_header` and `spanning`).
|
|
643
|
+
segment_rule: `iou` or `ioa`.
|
|
644
|
+
threshold_rows: The `iou`/`ioa` threshold of a cell with a row in order to conclude that the cell belongs to
|
|
645
|
+
the row.
|
|
646
|
+
threshold_cols: The `iou`/`ioa` threshold of a cell with a column in order to conclude that the cell belongs to
|
|
647
|
+
the column.
|
|
648
|
+
|
|
649
|
+
Returns:
|
|
650
|
+
A list of `SegmentationResult` for spanning cells.
|
|
619
651
|
"""
|
|
620
652
|
|
|
621
653
|
child_ann_ids = table.get_relationship(Relationships.CHILD)
|
|
@@ -751,21 +783,24 @@ class TableSegmentationService(PipelineComponent):
|
|
|
751
783
|
via intersection.
|
|
752
784
|
|
|
753
785
|
- Predicted rows are stretched horizontally to the edges of the table. Columns are stretched vertically. There is
|
|
754
|
-
also the option of stretching rows and columns so that they completely pave the table (set
|
|
755
|
-
=True).
|
|
786
|
+
also the option of stretching rows and columns so that they completely pave the table (set
|
|
787
|
+
`tile_table_with_items=True`).
|
|
756
788
|
|
|
757
789
|
- Next, rows and columns are given a row or column number by sorting them vertically or horizontally
|
|
758
790
|
according to the box center.
|
|
759
791
|
|
|
760
|
-
- The averages are then determined in pairs separately for rows and columns (more precisely: Iou /
|
|
761
|
-
intersection-over-union or ioa / intersection-over-area of rows and cells or columns and cells. A cell is
|
|
762
|
-
assigned a row position if the iou / ioa is above a defined threshold.
|
|
792
|
+
- The averages are then determined in pairs separately for rows and columns (more precisely: `Iou` /
|
|
793
|
+
intersection-over-union or `ioa` / intersection-over-area of rows and cells or columns and cells. A cell is
|
|
794
|
+
assigned a row position if the `iou` / `ioa` is above a defined threshold.
|
|
763
795
|
|
|
764
796
|
- The minimum row or column with which the cell was matched is used as the row and column of the cell. Row span /
|
|
765
797
|
col span result from the number of matched rows and columns.
|
|
766
798
|
|
|
767
|
-
|
|
768
|
-
|
|
799
|
+
Note:
|
|
800
|
+
It should be noted that this method means that cell positions can be assigned multiple times by different cells.
|
|
801
|
+
If this should be excluded, `TableSegmentationRefinementService` can be used to merge cells.
|
|
802
|
+
|
|
803
|
+
|
|
769
804
|
"""
|
|
770
805
|
|
|
771
806
|
def __init__(
|
|
@@ -783,18 +818,19 @@ class TableSegmentationService(PipelineComponent):
|
|
|
783
818
|
stretch_rule: Literal["left", "equal"] = "left",
|
|
784
819
|
):
|
|
785
820
|
"""
|
|
786
|
-
:
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
821
|
+
Args:
|
|
822
|
+
segment_rule: Rule to assign cell to row, columns resp. must be either `iou` or `ioa`.
|
|
823
|
+
threshold_rows: `iou`/`ioa` threshold for rows.
|
|
824
|
+
threshold_cols: `iou`/`ioa` threshold for columns.
|
|
825
|
+
tile_table_with_items: Will shift the left edge of rows vertically to coincide with the right edge of the
|
|
826
|
+
adjacent row. Will do a similar shifting with columns.
|
|
827
|
+
remove_iou_threshold_rows: `iou` threshold for removing overlapping rows.
|
|
828
|
+
remove_iou_threshold_cols: `iou` threshold for removing overlapping columns.
|
|
829
|
+
table_name: Layout type table.
|
|
830
|
+
cell_names: Layout type of cells.
|
|
831
|
+
item_names: Layout type of items (e.g. row and column).
|
|
832
|
+
sub_item_names: Cell types of sub items (e.g. row number and column number).
|
|
833
|
+
stretch_rule: Check the description in `tile_tables_with_items_per_table`.
|
|
798
834
|
"""
|
|
799
835
|
if segment_rule not in ("iou", "ioa"):
|
|
800
836
|
raise ValueError("segment_rule must be either iou or ioa")
|
|
@@ -878,10 +914,26 @@ class TableSegmentationService(PipelineComponent):
|
|
|
878
914
|
|
|
879
915
|
if table.image:
|
|
880
916
|
cells = table.image.get_annotation(category_names=self.cell_names)
|
|
881
|
-
number_of_rows = max(
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
917
|
+
number_of_rows = max(
|
|
918
|
+
cell.get_sub_category(CellType.ROW_NUMBER).category_id
|
|
919
|
+
for cell in cells
|
|
920
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
921
|
+
)
|
|
922
|
+
number_of_cols = max(
|
|
923
|
+
cell.get_sub_category(CellType.COLUMN_NUMBER).category_id
|
|
924
|
+
for cell in cells
|
|
925
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
926
|
+
)
|
|
927
|
+
max_row_span = max(
|
|
928
|
+
cell.get_sub_category(CellType.ROW_SPAN).category_id
|
|
929
|
+
for cell in cells
|
|
930
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
931
|
+
)
|
|
932
|
+
max_col_span = max(
|
|
933
|
+
cell.get_sub_category(CellType.COLUMN_SPAN).category_id
|
|
934
|
+
for cell in cells
|
|
935
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
936
|
+
)
|
|
885
937
|
# TODO: the summaries should be sub categories of the underlying ann
|
|
886
938
|
self.dp_manager.set_summary_annotation(
|
|
887
939
|
TableType.NUMBER_OF_ROWS,
|
|
@@ -945,28 +997,30 @@ class PubtablesSegmentationService(PipelineComponent):
|
|
|
945
997
|
`CellType.ROW_HEADER`, `CellType.COLUMN_HEADER`, `CellType.PROJECTED_ROW_HEADER`. For table recognition using
|
|
946
998
|
this service build a pipeline as follows:
|
|
947
999
|
|
|
948
|
-
|
|
949
|
-
|
|
1000
|
+
Example:
|
|
1001
|
+
```python
|
|
950
1002
|
layout = ImageLayoutService(layout_detector, to_image=True, crop_image=True)
|
|
951
1003
|
recognition = SubImageLayoutService(table_recognition_detector, LayoutType.TABLE, {1: 6, 2:7, 3:8, 4:9}, True)
|
|
952
1004
|
segment = PubtablesSegmentationService('ioa', 0.4, 0.4, True, 0.8, 0.8, 7)
|
|
953
|
-
...
|
|
954
|
-
|
|
955
1005
|
pipe = DoctectionPipe([layout, recognition, segment])
|
|
1006
|
+
```
|
|
956
1007
|
|
|
957
1008
|
Under the hood this service performs the following tasks:
|
|
958
1009
|
|
|
959
1010
|
- Stretching of rows and columns horizontally and vertically, so that the underlying table is fully tiled by rows
|
|
960
1011
|
and columns.
|
|
961
1012
|
- Enumerating rows and columns.
|
|
962
|
-
- For intersecting rows and columns it will create an
|
|
963
|
-
- Using spanning cells from the detector to determine their
|
|
1013
|
+
- For intersecting rows and columns it will create an `ImageAnnotation` of category `LayoutType.cell`.
|
|
1014
|
+
- Using spanning cells from the detector to determine their `row_number` and `column_number` position.
|
|
964
1015
|
- Using cells and spanning cells, it will generate a tiling of the table with cells. When some cells have a position
|
|
965
1016
|
with some spanning cells, it will deactivate those simple cells and prioritize the spanning cells.
|
|
966
1017
|
- Determining the HTML representation of table.
|
|
967
1018
|
|
|
968
|
-
|
|
969
|
-
|
|
1019
|
+
Info:
|
|
1020
|
+
Different from the `TableSegmentationService` this service does not require a refinement service: the advantage
|
|
1021
|
+
of this method is, that the segmentation can already be 'HTMLized'.
|
|
1022
|
+
|
|
1023
|
+
|
|
970
1024
|
"""
|
|
971
1025
|
|
|
972
1026
|
def __init__(
|
|
@@ -989,28 +1043,29 @@ class PubtablesSegmentationService(PipelineComponent):
|
|
|
989
1043
|
stretch_rule: Literal["left", "equal"] = "left",
|
|
990
1044
|
) -> None:
|
|
991
1045
|
"""
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1046
|
+
Args:
|
|
1047
|
+
segment_rule: Rule to assign spanning cells to row, columns resp. must be either `iou` or `ioa`.
|
|
1048
|
+
threshold_rows: `iou`/`ioa` threshold for rows.
|
|
1049
|
+
threshold_cols: `iou`/`ioa` threshold for columns.
|
|
1050
|
+
tile_table_with_items: Will shift the left edge of rows vertically to coincide with the right edge of the
|
|
1051
|
+
adjacent row. Will do a similar shifting with columns.
|
|
1052
|
+
remove_iou_threshold_rows: `iou` threshold for removing overlapping rows.
|
|
1053
|
+
remove_iou_threshold_cols: `iou` threshold for removing overlapping columns.
|
|
1054
|
+
table_name: Layout type table.
|
|
1055
|
+
cell_names: Layout type of cells.
|
|
1056
|
+
spanning_cell_names: Layout type of spanning cells.
|
|
1057
|
+
item_names: Layout type of items (e.g. row and column).
|
|
1058
|
+
sub_item_names: Layout type of sub items (e.g. row number and column number).
|
|
1059
|
+
item_header_cell_names: Layout type of item header cells (e.g. `CellType.COLUMN_HEADER`,
|
|
1060
|
+
`CellType.ROW_HEADER`).
|
|
1061
|
+
Note that column header, resp. row header will be first assigned to rows, resp.
|
|
1062
|
+
columns and then transferred to cells.
|
|
1063
|
+
item_header_thresholds: `iou`/`ioa` threshold for matching header cells with items. The first threshold
|
|
1064
|
+
corresponds to matching the first entry of `item_names`.
|
|
1065
|
+
cell_to_image: If set to `True` it will create an `Image` for `LayoutType.cell`.
|
|
1066
|
+
crop_cell_image: If set to `True` it will crop a numpy array image for `LayoutType.cell`. Requires
|
|
1067
|
+
`cell_to_image=True`.
|
|
1068
|
+
stretch_rule: Check the description in `tile_tables_with_items_per_table`.
|
|
1014
1069
|
"""
|
|
1015
1070
|
self.segment_rule = segment_rule
|
|
1016
1071
|
self.threshold_rows = threshold_rows
|
|
@@ -1166,10 +1221,26 @@ class PubtablesSegmentationService(PipelineComponent):
|
|
|
1166
1221
|
if table.image:
|
|
1167
1222
|
cells = table.image.get_annotation(category_names=self.cell_names)
|
|
1168
1223
|
if cells:
|
|
1169
|
-
number_of_rows = max(
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1224
|
+
number_of_rows = max(
|
|
1225
|
+
cell.get_sub_category(CellType.ROW_NUMBER).category_id
|
|
1226
|
+
for cell in cells
|
|
1227
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
1228
|
+
)
|
|
1229
|
+
number_of_cols = max(
|
|
1230
|
+
cell.get_sub_category(CellType.COLUMN_NUMBER).category_id
|
|
1231
|
+
for cell in cells
|
|
1232
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
1233
|
+
)
|
|
1234
|
+
max_row_span = max(
|
|
1235
|
+
cell.get_sub_category(CellType.ROW_SPAN).category_id
|
|
1236
|
+
for cell in cells
|
|
1237
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
1238
|
+
)
|
|
1239
|
+
max_col_span = max(
|
|
1240
|
+
cell.get_sub_category(CellType.COLUMN_SPAN).category_id
|
|
1241
|
+
for cell in cells
|
|
1242
|
+
if CellType.ROW_NUMBER in cell.sub_categories
|
|
1243
|
+
)
|
|
1173
1244
|
else:
|
|
1174
1245
|
number_of_rows = 0
|
|
1175
1246
|
number_of_cols = 0
|