Exemplo n.º 1
0
    def convert_mask(mask):
        polygons = mask_tools.mask_to_polygons(mask.image)

        return [
            Polygon(points=p, label=mask.label, z_order=mask.z_order,
                id=mask.id, attributes=mask.attributes, group=mask.group)
            for p in polygons
        ]
Exemplo n.º 2
0
    def test_mask_can_be_converted_to_polygon(self):
        mask = np.array([
            [0, 1, 1, 1, 0, 1, 1, 1, 1, 0],
            [0, 0, 1, 1, 0, 1, 0, 1, 0, 0],
            [0, 0, 0, 1, 0, 1, 1, 0, 0, 0],
            [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        ])
        expected = [
            [1, 0, 3, 0, 3, 2, 1, 0],
            [5, 0, 8, 0, 5, 3],
        ]

        computed = mask_tools.mask_to_polygons(mask)

        self.assertEqual(len(expected), len(computed))
Exemplo n.º 3
0
    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]
Exemplo n.º 4
0
def parse_xml_annotations(xml_data, annotations, input_zip):
    from datumaro.util.mask_tools import mask_to_polygons
    from io import BytesIO
    from lxml import etree as ET
    import numpy as np
    import os.path as osp
    from PIL import Image

    def parse_attributes(attributes_string):
        parsed = []
        if not attributes_string:
            return parsed

        read = attributes_string.split(',')
        read = [a.strip() for a in read if a.strip()]
        for attr in read:
            if '=' in attr:
                name, value = attr.split('=', maxsplit=1)
                parsed.append(annotations.Attribute(name, value))
            else:
                parsed.append(annotations.Attribute(attr, '1'))

        return parsed

    root_elem = ET.fromstring(xml_data)

    frame_number = annotations.match_frame(root_elem.find('filename').text)

    parsed_annotations = dict()
    group_assignments = dict()
    root_annotations = set()
    for obj_elem in root_elem.iter('object'):
        obj_id = int(obj_elem.find('id').text)

        ann_items = []

        attributes = []
        attributes_elem = obj_elem.find('attributes')
        if attributes_elem is not None and attributes_elem.text:
            attributes = parse_attributes(attributes_elem.text)

        occluded = False
        occluded_elem = obj_elem.find('occluded')
        if occluded_elem is not None and occluded_elem.text:
            occluded = (occluded_elem.text == 'yes')

        deleted = False
        deleted_elem = obj_elem.find('deleted')
        if deleted_elem is not None and deleted_elem.text:
            deleted = bool(int(deleted_elem.text))

        poly_elem = obj_elem.find('polygon')
        segm_elem = obj_elem.find('segm')
        type_elem = obj_elem.find('type')  # the only value is 'bounding_box'
        if poly_elem is not None:
            points = []
            for point_elem in poly_elem.iter('pt'):
                x = float(point_elem.find('x').text)
                y = float(point_elem.find('y').text)
                points.append(x)
                points.append(y)
            label = obj_elem.find('name').text
            if label and attributes:
                label_id = annotations._get_label_id(label)
                if label_id:
                    attributes = [
                        a for a in attributes
                        if annotations._get_attribute_id(label_id, a.name)
                    ]
                else:
                    attributes = []
            else:
                attributes = []

            if type_elem is not None and type_elem.text == 'bounding_box':
                xmin = min(points[::2])
                xmax = max(points[::2])
                ymin = min(points[1::2])
                ymax = max(points[1::2])
                ann_items.append(
                    annotations.LabeledShape(
                        type='rectangle',
                        frame=frame_number,
                        label=label,
                        points=[xmin, ymin, xmax, ymax],
                        occluded=occluded,
                        attributes=attributes,
                    ))
            else:
                ann_items.append(
                    annotations.LabeledShape(
                        type='polygon',
                        frame=frame_number,
                        label=label,
                        points=points,
                        occluded=occluded,
                        attributes=attributes,
                    ))
        elif segm_elem is not None:
            label = obj_elem.find('name').text
            if label and attributes:
                label_id = annotations._get_label_id(label)
                if label_id:
                    attributes = [
                        a for a in attributes
                        if annotations._get_attribute_id(label_id, a.name)
                    ]
                else:
                    attributes = []
            else:
                attributes = []

            mask_file = segm_elem.find('mask').text
            mask = input_zip.read(osp.join(_MASKS_DIR, mask_file))
            mask = np.asarray(Image.open(BytesIO(mask)).convert('L'))
            mask = (mask != 0)
            polygons = mask_to_polygons(mask)

            for polygon in polygons:
                ann_items.append(
                    annotations.LabeledShape(
                        type='polygon',
                        frame=frame_number,
                        label=label,
                        points=polygon,
                        occluded=occluded,
                        attributes=attributes,
                    ))

        if not deleted:
            parsed_annotations[obj_id] = ann_items

        parts_elem = obj_elem.find('parts')
        if parts_elem is not None:
            children_ids = []
            hasparts_elem = parts_elem.find('hasparts')
            if hasparts_elem is not None and hasparts_elem.text:
                children_ids = [int(c) for c in hasparts_elem.text.split(',')]

            parent_ids = []
            ispartof_elem = parts_elem.find('ispartof')
            if ispartof_elem is not None and ispartof_elem.text:
                parent_ids = [int(c) for c in ispartof_elem.text.split(',')]

            if children_ids and not parent_ids and hasparts_elem.text:
                root_annotations.add(obj_id)
            group_assignments[obj_id] = [None, children_ids]

    # assign a single group to the whole subtree
    current_group_id = 0
    annotations_to_visit = list(root_annotations)
    while annotations_to_visit:
        ann_id = annotations_to_visit.pop()
        ann_assignment = group_assignments[ann_id]
        group_id, children_ids = ann_assignment
        if group_id:
            continue

        if ann_id in root_annotations:
            current_group_id += 1  # start a new group

        group_id = current_group_id
        ann_assignment[0] = group_id

        # continue with children
        annotations_to_visit.extend(children_ids)

    assert current_group_id == len(root_annotations)

    for ann_id, ann_items in parsed_annotations.items():
        group_id = 0
        if ann_id in group_assignments:
            ann_assignment = group_assignments[ann_id]
            group_id = ann_assignment[0]

        for ann_item in ann_items:
            if group_id:
                ann_item = ann_item._replace(group=group_id)
            if isinstance(ann_item, annotations.LabeledShape):
                annotations.add_shape(ann_item)
            else:
                raise NotImplementedError()