Пример #1
0
    def _check_groups(self, annotations):
        check_groups = []
        for check_group_raw in self.conf.groups:
            check_group = set(l[0] for l in check_group_raw)
            optional = set(l[0] for l in check_group_raw if l[1])
            check_groups.append((check_group, optional))

        def _check_group(group_labels, group):
            for check_group, optional in check_groups:
                common = check_group & group_labels
                real_miss = check_group - common - optional
                extra = group_labels - check_group
                if common and (extra or real_miss):
                    self.add_item_error(WrongGroupError, group_labels,
                        check_group, group)
                    break

        groups = find_instances(annotations)
        for group in groups:
            group_labels = set()
            for ann in group:
                if not hasattr(ann, 'label'):
                    continue
                label = self._get_label_name(ann.label)

                if ann.group:
                    group_labels.add(label)
                else:
                    _check_group({label}, [ann])

            if not group_labels:
                continue
            _check_group(group_labels, group)
Пример #2
0
    def _make_mergers(self, sources):
        def _make(c, **kwargs):
            kwargs.update(attr.asdict(self.conf))
            fields = attr.fields_dict(c)
            return c(**{ k: v for k, v in kwargs.items() if k in fields },
                context=self)

        def _for_type(t, **kwargs):
            if t is AnnotationType.label:
                return _make(LabelMerger, **kwargs)
            elif t is AnnotationType.bbox:
                return _make(BboxMerger, **kwargs)
            elif t is AnnotationType.mask:
                return _make(MaskMerger, **kwargs)
            elif t is AnnotationType.polygon:
                return _make(PolygonMerger, **kwargs)
            elif t is AnnotationType.polyline:
                return _make(LineMerger, **kwargs)
            elif t is AnnotationType.points:
                return _make(PointsMerger, **kwargs)
            elif t is AnnotationType.caption:
                return _make(CaptionsMerger, **kwargs)
            else:
                raise NotImplementedError("Type %s is not supported" % t)

        instance_map = {}
        for s in sources:
            s_instances = find_instances(s)
            for inst in s_instances:
                inst_bbox = max_bbox([a for a in inst if a.type in
                    {AnnotationType.polygon,
                     AnnotationType.mask, AnnotationType.bbox}
                ])
                for ann in inst:
                    instance_map[id(ann)] = [inst, inst_bbox]

        self._mergers = { t: _for_type(t, instance_map=instance_map)
            for t in AnnotationType }
Пример #3
0
 def find_instances(cls, annotations):
     return anno_tools.find_instances(cls.find_instance_anns(annotations))
Пример #4
0
 def _find_instances(annotations):
     return find_instances(
         a for a in annotations
         if a.type in {AnnotationType.bbox, AnnotationType.mask})
Пример #5
0
 def find_instances(annotations):
     return find_instances(
         a for a in annotations
         if a.type in {AnnotationType.polygon, AnnotationType.mask})
Пример #6
0
    def _save_item_annotations(
        self,
        item,
        label_description_writer,
        bbox_description_writer,
        mask_description_writer,
        label_categories,
        image_meta,
    ):
        next_box_id = 0

        existing_box_ids = {
            annotation.attributes['box_id']
            for annotation in item.annotations
            if annotation.type is AnnotationType.mask
            if 'box_id' in annotation.attributes
        }

        for instance in find_instances(item.annotations):
            instance_box = next(
                (a for a in instance if a.type is AnnotationType.bbox),
                None)

            for annotation in instance:
                if annotation.type is AnnotationType.label:
                    label_description_writer.writerow({
                        'ImageID': item.id,
                        'LabelName': label_categories[annotation.label].name,
                        'Confidence': str(annotation.attributes.get('score', 1)),
                    })
                elif annotation.type is AnnotationType.bbox:
                    if item.has_image and item.image.size is not None:
                        image_meta[item.id] = item.image.size
                        height, width = item.image.size
                    else:
                        log.warning(
                            "Can't encode box for item '%s' due to missing image file",
                            item.id)
                        continue

                    bbox_description_writer.writerow({
                        'ImageID': item.id,
                        'LabelName': label_categories[annotation.label].name,
                        'Confidence': str(annotation.attributes.get('score', 1)),
                        'XMin': annotation.x / width,
                        'YMin': annotation.y / height,
                        'XMax': (annotation.x + annotation.w) / width,
                        'YMax': (annotation.y + annotation.h) / height,
                        **{
                            bool_attr.oid_name:
                                int(annotation.attributes.get(bool_attr.datumaro_name, -1))
                            for bool_attr in OpenImagesPath.BBOX_BOOLEAN_ATTRIBUTES
                        },
                    })
                elif annotation.type is AnnotationType.mask:
                    mask_dir = osp.join(self._save_dir, OpenImagesPath.MASKS_DIR, item.subset)

                    box_id_str = annotation.attributes.get('box_id')

                    if box_id_str:
                        if _RE_INVALID_PATH_COMPONENT.fullmatch(box_id_str):
                            raise UnsupportedBoxIdError(item_id=item.id, box_id=box_id_str)
                    else:
                        # find a box ID that isn't used in any other annotations
                        while True:
                            box_id_str = format(next_box_id, "08x")
                            next_box_id += 1
                            if box_id_str not in existing_box_ids:
                                break

                    label_name = label_categories[annotation.label].name
                    mask_file_name = '%s_%s_%s.png' % (
                        make_file_name(item.id), make_file_name(label_name), box_id_str,
                    )

                    box_coords = {}

                    if instance_box is not None:
                        if item.has_image and item.image.size is not None:
                            image_meta[item.id] = item.image.size
                            height, width = item.image.size

                            box_coords = {
                                'BoxXMin': instance_box.x / width,
                                'BoxXMax': (instance_box.x + instance_box.w) / width,
                                'BoxYMin': instance_box.y / height,
                                'BoxYMax': (instance_box.y + instance_box.h) / height,
                            }
                        else:
                            log.warning(
                                "Can't encode box coordinates for a mask"
                                    " for item '%s' due to missing image file",
                                item.id)

                    mask_description_writer.writerow({
                        'MaskPath': mask_file_name,
                        'ImageID': item.id,
                        'LabelName': label_name,
                        'BoxID': box_id_str,
                        **box_coords,
                        'PredictedIoU':
                            annotation.attributes.get('predicted_iou', ''),
                    })

                    save_image(osp.join(mask_dir, mask_file_name),
                        annotation.image, create_dir=True)