From cf0a3e8fc6b4d835f5f50b9c000ab4a3812950e1 Mon Sep 17 00:00:00 2001 From: Hongyuan Zhang <66273343+Alias-z@users.noreply.github.com> Date: Fri, 31 May 2024 20:30:02 +0200 Subject: [PATCH 1/3] Fix TypeError: 'GeometryCollection' object is not subscriptable when slicing COCO Solution to https://github.com/obss/sahi/discussions/1011 by adding a filter for Polygon only --- sahi/utils/coco.py | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/sahi/utils/coco.py b/sahi/utils/coco.py index e84f2f3d3..a7cc76e4b 100644 --- a/sahi/utils/coco.py +++ b/sahi/utils/coco.py @@ -14,7 +14,7 @@ from typing import Dict, List, Optional, Set, Union import numpy as np -from shapely import MultiPolygon +from shapely import MultiPolygon, Polygon, GeometryCollection from shapely.validation import make_valid from tqdm import tqdm @@ -224,12 +224,29 @@ def __init__( self._shapely_annotation = shapely_annotation def get_sliced_coco_annotation(self, slice_bbox: List[int]): + + def filter_polygons(geometry): + """ + This function checks if the geometry is a Polygon or MultiPolygon and filters accordingly. + It returns a MultiPolygon made only from Polygon components. + """ + if isinstance(geometry, Polygon): + return MultiPolygon([geometry]) + elif isinstance(geometry, MultiPolygon): + return geometry + elif isinstance(geometry, GeometryCollection): + polygons = [geom for geom in geometry.geoms if isinstance(geom, Polygon)] + if polygons: + return MultiPolygon(polygons) + return MultiPolygon() # Return an empty MultiPolygon if no Polygon geometries are found + shapely_polygon = box(slice_bbox[0], slice_bbox[1], slice_bbox[2], slice_bbox[3]) samp = self._shapely_annotation.multipolygon if not samp.is_valid: valid = make_valid(samp) - if not isinstance(valid, MultiPolygon): - valid = MultiPolygon([valid]) + valid = filter_polygons(valid) + # if not isinstance(valid, MultiPolygon): + # valid = MultiPolygon([valid]) self._shapely_annotation.multipolygon = valid intersection_shapely_annotation = self._shapely_annotation.get_intersection(shapely_polygon) return CocoAnnotation.from_shapely_annotation( From 0afbf5be30ca1cd46f89c30b767c8815f153881b Mon Sep 17 00:00:00 2001 From: Hongyuan Zhang <66273343+Alias-z@users.noreply.github.com> Date: Sun, 2 Jun 2024 20:00:30 +0200 Subject: [PATCH 2/3] Test lint fixing with isort and black --- sahi/utils/coco.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sahi/utils/coco.py b/sahi/utils/coco.py index a7cc76e4b..de7d11eb8 100644 --- a/sahi/utils/coco.py +++ b/sahi/utils/coco.py @@ -14,7 +14,7 @@ from typing import Dict, List, Optional, Set, Union import numpy as np -from shapely import MultiPolygon, Polygon, GeometryCollection +from shapely import GeometryCollection, MultiPolygon, Polygon from shapely.validation import make_valid from tqdm import tqdm @@ -227,8 +227,10 @@ def get_sliced_coco_annotation(self, slice_bbox: List[int]): def filter_polygons(geometry): """ - This function checks if the geometry is a Polygon or MultiPolygon and filters accordingly. - It returns a MultiPolygon made only from Polygon components. + Filters out and returns only Polygon or MultiPolygon components of a geometry. + If geometry is a Polygon, it converts it into a MultiPolygon. + If it's a GeometryCollection, it filters to create a MultiPolygon from any Polygons in the collection. + Returns an empty MultiPolygon if no Polygon or MultiPolygon components are found. """ if isinstance(geometry, Polygon): return MultiPolygon([geometry]) @@ -236,17 +238,14 @@ def filter_polygons(geometry): return geometry elif isinstance(geometry, GeometryCollection): polygons = [geom for geom in geometry.geoms if isinstance(geom, Polygon)] - if polygons: - return MultiPolygon(polygons) - return MultiPolygon() # Return an empty MultiPolygon if no Polygon geometries are found + return MultiPolygon(polygons) if polygons else MultiPolygon() + return MultiPolygon() shapely_polygon = box(slice_bbox[0], slice_bbox[1], slice_bbox[2], slice_bbox[3]) samp = self._shapely_annotation.multipolygon if not samp.is_valid: valid = make_valid(samp) valid = filter_polygons(valid) - # if not isinstance(valid, MultiPolygon): - # valid = MultiPolygon([valid]) self._shapely_annotation.multipolygon = valid intersection_shapely_annotation = self._shapely_annotation.get_intersection(shapely_polygon) return CocoAnnotation.from_shapely_annotation( From fad86cfdf97b1649bb22ecabaf5086b088e817ba Mon Sep 17 00:00:00 2001 From: Hongyuan Zhang <66273343+Alias-z@users.noreply.github.com> Date: Sun, 2 Jun 2024 22:53:28 +0200 Subject: [PATCH 3/3] Attempt with run_code_style format --- sahi/utils/coco.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sahi/utils/coco.py b/sahi/utils/coco.py index de7d11eb8..942561cb7 100644 --- a/sahi/utils/coco.py +++ b/sahi/utils/coco.py @@ -224,7 +224,6 @@ def __init__( self._shapely_annotation = shapely_annotation def get_sliced_coco_annotation(self, slice_bbox: List[int]): - def filter_polygons(geometry): """ Filters out and returns only Polygon or MultiPolygon components of a geometry.