def from_instance_masks(instance_masks, instance_ids=None, instance_labels=None): from datumaro.util.mask_tools import merge_masks if instance_ids is not None: assert len(instance_ids) == len(instance_masks) else: instance_ids = [None] * len(instance_masks) if instance_labels is not None: assert len(instance_labels) == len(instance_masks) else: instance_labels = [None] * len(instance_masks) instance_masks = sorted(zip(instance_masks, instance_ids, instance_labels), key=lambda m: m[0].z_order) instance_mask = [ m.as_instance_mask(id if id is not None else 1 + idx) for idx, (m, id, _) in enumerate(instance_masks) ] instance_mask = merge_masks(instance_mask) cls_mask = [m.as_class_mask(c) for m, _, c in instance_masks] cls_mask = merge_masks(cls_mask) return __class__(class_mask=cls_mask, instance_mask=instance_mask)
def crop_segments(cls, instances, img_width, img_height): instances = sorted(instances, key=lambda x: x[0].z_order) segment_map = [] segments = [] for inst_idx, (_, polygons, mask, _) in enumerate(instances): if polygons: segment_map.extend(inst_idx for p in polygons) segments.extend(polygons) elif mask is not None: segment_map.append(inst_idx) segments.append(mask) segments = mask_tools.crop_covered_segments(segments, img_width, img_height) for inst_idx, inst in enumerate(instances): new_segments = [ s for si_id, s in zip(segment_map, segments) if si_id == inst_idx ] if not new_segments: inst[1] = [] inst[2] = None continue if inst[1]: inst[1] = sum(new_segments, []) else: mask = mask_tools.merge_masks(new_segments) inst[2] = mask_tools.mask_to_rle(mask) return instances
def find_instance_parts(self, group, img_width, img_height): boxes = [a for a in group if a.type == AnnotationType.bbox] polygons = [a for a in group if a.type == AnnotationType.polygon] masks = [a for a in group if a.type == AnnotationType.mask] anns = boxes + polygons + masks leader = anno_tools.find_group_leader(anns) bbox = anno_tools.max_bbox(anns) mask = None polygons = [p.points for p in polygons] if self._context._segmentation_mode == SegmentationMode.guess: use_masks = True == leader.attributes.get( 'is_crowd', find(masks, lambda x: x.label == leader.label) is not None) elif self._context._segmentation_mode == SegmentationMode.polygons: use_masks = False elif self._context._segmentation_mode == SegmentationMode.mask: use_masks = True else: raise NotImplementedError("Unexpected segmentation mode '%s'" % \ self._context._segmentation_mode) if use_masks: if polygons: mask = mask_tools.rles_to_mask(polygons, img_width, img_height) if masks: masks = (m.image for m in masks) if mask is not None: masks += chain(masks, [mask]) mask = mask_tools.merge_masks(masks) if mask is not None: mask = mask_tools.mask_to_rle(mask) polygons = [] else: if masks: mask = mask_tools.merge_masks(m.image for m in masks) polygons += mask_tools.mask_to_polygons(mask) mask = None return [leader, polygons, mask, bbox]
def _find_instance_parts(self, group, img_width, img_height): boxes = [a for a in group if a.type == AnnotationType.bbox] masks = [a for a in group if a.type == AnnotationType.mask] anns = boxes + masks leader = find_group_leader(anns) bbox = max_bbox(anns) mask = None if self._save_masks: mask = merge_masks([m.image for m in masks]) return [leader, mask, bbox]
def test_can_merge_masks(self): masks = [ np.array([0, 2, 4, 0, 0, 1]), np.array([0, 1, 1, 0, 2, 0]), np.array([0, 0, 2, 3, 0, 0]), ] expected = \ np.array([0, 1, 2, 3, 2, 1]) actual = mask_tools.merge_masks(masks) self.assertTrue(np.array_equal(expected, actual), '%s\nvs.\n%s' % (expected, actual))
def _save_annotations(self, item, anno_dir): masks = [a for a in item.annotations if a.type == AnnotationType.mask] if not masks: return instance_ids = [int(a.attributes['track_id']) for a in masks] masks = sorted(zip(masks, instance_ids), key=lambda e: e[0].z_order) mask = merge_masks( (m.image, MotsPath.MAX_INSTANCES * (1 + m.label) + id) for m, id in masks) save_image(osp.join(anno_dir, item.id + '.png'), mask, create_dir=True, dtype=np.uint16)
def merge_segments(cls, instance, img_width, img_height, include_polygons=False): polygons = [a for a in instance if a.type == AnnotationType.polygon] masks = [a for a in instance if a.type == AnnotationType.mask] if not polygons and not masks: return [] if not polygons and len(masks) == 1: return masks leader = find_group_leader(polygons + masks) instance = [] # Build the resulting mask mask = None if include_polygons and polygons: polygons = [p.points for p in polygons] mask = mask_tools.rles_to_mask(polygons, img_width, img_height) else: instance += polygons # keep unused polygons if masks: masks = (m.image for m in masks) if mask is not None: masks = chain(masks, [mask]) mask = mask_tools.merge_masks(masks) if mask is None: return instance mask = mask_tools.mask_to_rle(mask) mask = mask_utils.frPyObjects(mask, *mask['size']) instance.append( RleMask(rle=mask, label=leader.label, z_order=leader.z_order, id=leader.id, attributes=leader.attributes, group=leader.group)) return instance
def save_annotations(self, item): if not item.has_image: return ann_filename = item.id + CocoPath.PANOPTIC_EXT segments_info = list() masks = [] next_id = self._min_ann_id for ann in item.annotations: if ann.type != AnnotationType.mask: continue if not ann.id: ann.id = next_id next_id += 1 segment_info = {} segment_info['id'] = ann.id segment_info['category_id'] = cast(ann.label, int, -1) + 1 segment_info['area'] = float(ann.get_area()) segment_info['bbox'] = [float(p) for p in ann.get_bbox()] segment_info['iscrowd'] = cast(ann.attributes.get("is_crowd"), int, 0) segments_info.append(segment_info) masks.append(ann) if not masks: return pan_format = mask_tools.merge_masks((m.image, m.id) for m in masks) save_image(osp.join(self._context._segmentation_dir, ann_filename), mask_tools.index2bgr(pan_format), create_dir=True) elem = { 'image_id': self._get_image_id(item), 'file_name': ann_filename, 'segments_info': segments_info } self.annotations.append(elem)