Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 1.0.10

* Remove merging logic that's no longer used

## 1.0.9

* Make OD model loading thread safe
Expand Down
39 changes: 0 additions & 39 deletions test_unstructured_inference/test_elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@
import numpy as np
import pytest

from unstructured_inference.constants import ElementType
from unstructured_inference.inference import elements
from unstructured_inference.inference.elements import (
ImageTextRegion,
Rectangle,
TextRegion,
TextRegions,
)
from unstructured_inference.inference.layoutelement import (
LayoutElement,
LayoutElements,
clean_layoutelements,
clean_layoutelements_for_class,
merge_inferred_layout_with_extracted_layout,
partition_groups_from_regions,
separate,
)
Expand Down Expand Up @@ -297,40 +292,6 @@ def test_separate(rect1, rect2):
# assert not rect1.intersects(rect2) #TODO: fix this test


def test_merge_inferred_layout_with_extracted_layout():
inferred_layout = [
LayoutElement.from_coords(453, 322, 1258, 408, text=None, type=ElementType.SECTION_HEADER),
LayoutElement.from_coords(387, 477, 1320, 537, text=None, type=ElementType.TEXT),
]

extracted_layout = [
TextRegion.from_coords(438, 318, 1272, 407, text="Example Section Header"),
TextRegion.from_coords(377, 469, 1335, 535, text="Example Title"),
]

extracted_layout_with_full_page_image = [
ImageTextRegion.from_coords(0, 0, 1700, 2200, text="Example Section Header"),
]

merged_layout = merge_inferred_layout_with_extracted_layout(
inferred_layout=inferred_layout,
extracted_layout=extracted_layout,
page_image_size=(1700, 2200),
)
assert merged_layout[0].type == ElementType.SECTION_HEADER
assert merged_layout[0].text == "Example Section Header"
assert merged_layout[1].type == ElementType.TEXT
assert merged_layout[1].text == "Example Title"

# case: extracted layout with a full page image
merged_layout = merge_inferred_layout_with_extracted_layout(
inferred_layout=inferred_layout,
extracted_layout=extracted_layout_with_full_page_image,
page_image_size=(1700, 2200),
)
assert merged_layout == inferred_layout


def test_clean_layoutelements(test_layoutelements):
elements = clean_layoutelements(test_layoutelements).as_list()
assert len(elements) == 2
Expand Down
2 changes: 1 addition & 1 deletion unstructured_inference/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.0.9" # pragma: no cover
__version__ = "1.0.10" # pragma: no cover
1 change: 0 additions & 1 deletion unstructured_inference/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class Source(Enum):
YOLOX = "yolox"
DETECTRON2_ONNX = "detectron2_onnx"
DETECTRON2_LP = "detectron2_lp"
MERGED = "merged"


class ElementType:
Expand Down
110 changes: 1 addition & 109 deletions unstructured_inference/inference/layoutelement.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,18 @@
from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Collection, Iterable, List, Optional
from typing import Any, Iterable, List, Optional

import numpy as np
from pandas import DataFrame
from scipy.sparse.csgraph import connected_components

from unstructured_inference.config import inference_config
from unstructured_inference.constants import (
FULL_PAGE_REGION_THRESHOLD,
ElementType,
)
from unstructured_inference.inference.elements import (
ImageTextRegion,
Rectangle,
TextRegion,
TextRegions,
coords_intersections,
grow_region_to_match_region,
region_bounding_boxes_are_almost_the_same,
)

EPSILON_AREA = 1e-7
Expand Down Expand Up @@ -221,107 +214,6 @@ def from_region(cls, region: TextRegion):
return cls(text=text, source=source, type=type, prob=prob, bbox=region.bbox)


def merge_inferred_layout_with_extracted_layout(
inferred_layout: Collection[LayoutElement],
extracted_layout: Collection[TextRegion],
page_image_size: tuple,
same_region_threshold: float = inference_config.LAYOUT_SAME_REGION_THRESHOLD,
subregion_threshold: float = inference_config.LAYOUT_SUBREGION_THRESHOLD,
) -> List[LayoutElement]:
"""Merge two layouts to produce a single layout."""
extracted_elements_to_add: List[TextRegion] = []
inferred_regions_to_remove = []
w, h = page_image_size
full_page_region = Rectangle(0, 0, w, h)
for extracted_region in extracted_layout:
extracted_is_image = isinstance(extracted_region, ImageTextRegion)
if extracted_is_image:
# Skip extracted images for this purpose, we don't have the text from them and they
# don't provide good text bounding boxes.

is_full_page_image = region_bounding_boxes_are_almost_the_same(
extracted_region.bbox,
full_page_region,
FULL_PAGE_REGION_THRESHOLD,
)

if is_full_page_image:
continue
region_matched = False
for inferred_region in inferred_layout:

if inferred_region.bbox.intersects(extracted_region.bbox):
same_bbox = region_bounding_boxes_are_almost_the_same(
inferred_region.bbox,
extracted_region.bbox,
same_region_threshold,
)
inferred_is_subregion_of_extracted = inferred_region.bbox.is_almost_subregion_of(
extracted_region.bbox,
subregion_threshold=subregion_threshold,
)
inferred_is_text = inferred_region.type not in (
ElementType.FIGURE,
ElementType.IMAGE,
ElementType.PAGE_BREAK,
ElementType.TABLE,
)
extracted_is_subregion_of_inferred = extracted_region.bbox.is_almost_subregion_of(
inferred_region.bbox,
subregion_threshold=subregion_threshold,
)
either_region_is_subregion_of_other = (
inferred_is_subregion_of_extracted or extracted_is_subregion_of_inferred
)
if same_bbox:
# Looks like these represent the same region
if extracted_is_image:
# keep extracted region, remove inferred region
inferred_regions_to_remove.append(inferred_region)
else:
# keep inferred region, remove extracted region
grow_region_to_match_region(inferred_region.bbox, extracted_region.bbox)
inferred_region.text = extracted_region.text
region_matched = True
elif extracted_is_subregion_of_inferred and inferred_is_text:
if extracted_is_image:
# keep both extracted and inferred regions
region_matched = False
else:
# keep inferred region, remove extracted region
grow_region_to_match_region(inferred_region.bbox, extracted_region.bbox)
region_matched = True
elif (
either_region_is_subregion_of_other
and inferred_region.type != ElementType.TABLE
):
# keep extracted region, remove inferred region
inferred_regions_to_remove.append(inferred_region)
if not region_matched:
extracted_elements_to_add.append(extracted_region)
# Need to classify the extracted layout elements we're keeping.
categorized_extracted_elements_to_add = [
LayoutElement(
text=el.text,
type=(
ElementType.IMAGE
if isinstance(el, ImageTextRegion)
else ElementType.UNCATEGORIZED_TEXT
),
source=el.source,
bbox=el.bbox,
)
for el in extracted_elements_to_add
]
inferred_regions_to_add = [
region for region in inferred_layout if region not in inferred_regions_to_remove
]

final_layout = categorized_extracted_elements_to_add + inferred_regions_to_add

return final_layout


def separate(region_a: Rectangle, region_b: Rectangle):
"""Reduce leftmost rectangle to don't overlap with the other"""

Expand Down