|
1 |
| -from typing import Callable, Optional, Tuple, Union |
| 1 | +from typing import Callable, Optional, Tuple, Union, List |
2 | 2 |
|
3 | 3 | import numpy as np
|
4 | 4 | from pydantic.class_validators import validator
|
5 |
| -from rasterio.features import shapes |
6 |
| -from shapely.geometry import MultiPolygon, shape |
| 5 | +from shapely.geometry import MultiPolygon, Polygon |
7 | 6 | import cv2
|
8 | 7 |
|
9 | 8 | from ..data import MaskData
|
@@ -39,12 +38,23 @@ class Mask(Geometry):
|
39 | 38 | @property
|
40 | 39 | def geometry(self):
|
41 | 40 | mask = self.draw(color=1)
|
42 |
| - polygons = ( |
43 |
| - shape(shp) |
44 |
| - for shp, val in shapes(mask, mask=None) |
45 |
| - # ignore if shape is area of smaller than 1 pixel |
46 |
| - if val >= 1) |
47 |
| - return MultiPolygon(polygons).__geo_interface__ |
| 41 | + contours, hierarchy = cv2.findContours(image=mask, |
| 42 | + mode=cv2.RETR_TREE, |
| 43 | + method=cv2.CHAIN_APPROX_NONE) |
| 44 | + |
| 45 | + holes = [] |
| 46 | + external_contours = [] |
| 47 | + for i in range(len(contours)): |
| 48 | + if hierarchy[0, i, 3] != -1: |
| 49 | + #determined to be a hole based on contour hierarchy |
| 50 | + holes.append(contours[i]) |
| 51 | + else: |
| 52 | + external_contours.append(contours[i]) |
| 53 | + |
| 54 | + external_polygons = self._extract_polygons_from_contours( |
| 55 | + external_contours) |
| 56 | + holes = self._extract_polygons_from_contours(holes) |
| 57 | + return external_polygons.difference(holes).__geo_interface__ |
48 | 58 |
|
49 | 59 | def draw(self,
|
50 | 60 | height: Optional[int] = None,
|
@@ -86,6 +96,11 @@ def draw(self,
|
86 | 96 | canvas[mask.astype(np.bool)] = color
|
87 | 97 | return canvas
|
88 | 98 |
|
| 99 | + def _extract_polygons_from_contours(self, contours: List) -> MultiPolygon: |
| 100 | + contours = map(np.squeeze, contours) |
| 101 | + polygons = map(Polygon, contours) |
| 102 | + return MultiPolygon(polygons) |
| 103 | + |
89 | 104 | def create_url(self, signer: Callable[[bytes], str]) -> str:
|
90 | 105 | """
|
91 | 106 | Update the segmentation mask to have a url.
|
|
0 commit comments