Skip to content
This repository has been archived by the owner on Dec 15, 2021. It is now read-only.

Commit

Permalink
Add RLE size check for SegmentationMask (facebookresearch#859)
Browse files Browse the repository at this point in the history
* support RLE and binary mask

* do not convert to numpy

* be consistent with Detectron

* delete wrong comment

* [WIP] add tests for segmentation_mask

* update tests

* minor change

* Refactored segmentation_mask.py

* Add unit test for segmentation_mask.py

* Add RLE support for BinaryMaskList

* PEP8 black formatting

* Minor patch

* Use internal  that handles 0 channels

* Fix polygon slicing

* Revert "Pr150"

* Add RLE size check for SegmentationMask
  • Loading branch information
botcs authored and fmassa committed Jun 4, 2019
1 parent 5f4e5a8 commit 657f280
Showing 1 changed file with 44 additions and 12 deletions.
56 changes: 44 additions & 12 deletions maskrcnn_benchmark/structures/segmentation_mask.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,31 +48,53 @@ def __init__(self, masks, size):
initializing source data intact.
"""

assert isinstance(size, (list, tuple))
assert len(size) == 2

if isinstance(masks, torch.Tensor):
# The raw data representation is passed as argument
masks = masks.clone()
elif isinstance(masks, (list, tuple)):
if len(masks) == 0:
masks = torch.empty([0, size[1], size[0]]) # num_instances = 0!
masks = torch.empty([0, size[1], size[0]]) # num_instances = 0!
elif isinstance(masks[0], torch.Tensor):
masks = torch.stack(masks, dim=2).clone()
elif isinstance(masks[0], dict) and "counts" in masks[0]:
# RLE interpretation
assert all(
[(size[1], size[0]) == tuple(inst["size"]) for inst in masks]
) # in RLE, height come first in "size"
rle_sizes = [tuple(inst["size"]) for inst in masks]

masks = mask_utils.decode(masks) # [h, w, n]
masks = torch.tensor(masks).permute(2, 0, 1) # [n, h, w]

assert rle_sizes.count(rle_sizes[0]) == len(rle_sizes), (
"All the sizes must be the same size: %s" % rle_sizes
)

# in RLE, height come first in "size"
rle_height, rle_width = rle_sizes[0]
assert masks.shape[1] == rle_height
assert masks.shape[2] == rle_width

width, height = size
if width != rle_width or height != rle_height:
masks = interpolate(
input=masks[None].float(),
size=(height, width),
mode="bilinear",
align_corners=False,
)[0].type_as(masks)
else:
RuntimeError(
"Type of `masks[0]` could not be interpreted: %s" % type(masks)
"Type of `masks[0]` could not be interpreted: %s"
% type(masks)
)
elif isinstance(masks, BinaryMaskList):
# just hard copy the BinaryMaskList instance's underlying data
masks = masks.masks.clone()
else:
RuntimeError(
"Type of `masks` argument could not be interpreted:%s" % type(masks)
"Type of `masks` argument could not be interpreted:%s"
% type(masks)
)

if len(masks.shape) == 2:
Expand Down Expand Up @@ -155,7 +177,9 @@ def _findContours(self):
reshaped_contour = []
for entity in contour:
assert len(entity.shape) == 3
assert entity.shape[1] == 1, "Hierarchical contours are not allowed"
assert (
entity.shape[1] == 1
), "Hierarchical contours are not allowed"
reshaped_contour.append(entity.reshape(-1).tolist())
contours.append(reshaped_contour)
return contours
Expand Down Expand Up @@ -206,7 +230,8 @@ def __init__(self, polygons, size):

else:
RuntimeError(
"Type of argument `polygons` is not allowed:%s" % (type(polygons))
"Type of argument `polygons` is not allowed:%s"
% (type(polygons))
)

""" This crashes the training way too many times...
Expand Down Expand Up @@ -278,7 +303,9 @@ def resize(self, size):
assert isinstance(size, (int, float))
size = size, size

ratios = tuple(float(s) / float(s_orig) for s, s_orig in zip(size, self.size))
ratios = tuple(
float(s) / float(s_orig) for s, s_orig in zip(size, self.size)
)

if ratios[0] == ratios[1]:
ratio = ratios[0]
Expand Down Expand Up @@ -349,15 +376,18 @@ def __init__(self, polygons, size):
type(polygons[0][0])
)
else:
assert isinstance(polygons[0], PolygonInstance), str(type(polygons[0]))
assert isinstance(polygons[0], PolygonInstance), str(
type(polygons[0])
)

elif isinstance(polygons, PolygonList):
size = polygons.size
polygons = polygons.polygons

else:
RuntimeError(
"Type of argument `polygons` is not allowed:%s" % (type(polygons))
"Type of argument `polygons` is not allowed:%s"
% (type(polygons))
)

assert isinstance(size, (list, tuple)), str(type(size))
Expand Down Expand Up @@ -404,7 +434,9 @@ def to(self, *args, **kwargs):

def convert_to_binarymask(self):
if len(self) > 0:
masks = torch.stack([p.convert_to_binarymask() for p in self.polygons])
masks = torch.stack(
[p.convert_to_binarymask() for p in self.polygons]
)
else:
size = self.size
masks = torch.empty([0, size[1], size[0]], dtype=torch.uint8)
Expand Down

0 comments on commit 657f280

Please sign in to comment.