|
7 | 7 | import mmcv
|
8 | 8 | import numpy as np
|
9 | 9 | import pycocotools.mask as maskUtils
|
| 10 | +import shapely.geometry as geometry |
10 | 11 | import torch
|
11 | 12 | from mmcv.ops.roi_align import roi_align
|
12 | 13 |
|
@@ -753,15 +754,40 @@ def crop(self, bbox):
|
753 | 754 | if len(self.masks) == 0:
|
754 | 755 | cropped_masks = PolygonMasks([], h, w)
|
755 | 756 | else:
|
| 757 | + # reference: https://github.com/facebookresearch/fvcore/blob/main/fvcore/transforms/transform.py # noqa |
| 758 | + crop_box = geometry.box(x1, y1, x2, y2).buffer(0.0) |
756 | 759 | cropped_masks = []
|
757 | 760 | for poly_per_obj in self.masks:
|
758 | 761 | cropped_poly_per_obj = []
|
759 | 762 | for p in poly_per_obj:
|
760 |
| - # pycocotools will clip the boundary |
761 | 763 | p = p.copy()
|
762 |
| - p[0::2] = p[0::2] - bbox[0] |
763 |
| - p[1::2] = p[1::2] - bbox[1] |
764 |
| - cropped_poly_per_obj.append(p) |
| 764 | + p = geometry.Polygon(p.reshape(-1, 2)).buffer(0.0) |
| 765 | + # polygon must be valid to perform intersection. |
| 766 | + if not p.is_valid: |
| 767 | + continue |
| 768 | + cropped = p.intersection(crop_box) |
| 769 | + if cropped.is_empty: |
| 770 | + continue |
| 771 | + if isinstance(cropped, |
| 772 | + geometry.collection.BaseMultipartGeometry): |
| 773 | + cropped = cropped.geoms |
| 774 | + else: |
| 775 | + cropped = [cropped] |
| 776 | + # one polygon may be cropped to multiple ones |
| 777 | + for poly in cropped: |
| 778 | + # ignore lines or points |
| 779 | + if not isinstance( |
| 780 | + poly, geometry.Polygon) or not poly.is_valid: |
| 781 | + continue |
| 782 | + coords = np.asarray(poly.exterior.coords) |
| 783 | + # remove an extra identical vertex at the end |
| 784 | + coords = coords[:-1] |
| 785 | + coords[:, 0] -= x1 |
| 786 | + coords[:, 1] -= y1 |
| 787 | + cropped_poly_per_obj.append(coords.reshape(-1)) |
| 788 | + |
| 789 | + if len(cropped_poly_per_obj) == 0: |
| 790 | + cropped_poly_per_obj = [np.array([0, 0, 0, 0, 0, 0])] |
765 | 791 | cropped_masks.append(cropped_poly_per_obj)
|
766 | 792 | cropped_masks = PolygonMasks(cropped_masks, h, w)
|
767 | 793 | return cropped_masks
|
|
0 commit comments