Exemplo n.º 1
0
 def write(self, loc):
     f = File(loc, self.root, suffix='.json')
     imfile = self.imfiles[loc]
     lmdict = LabelmeDict.gen_data(imfile)
     for label, ann in self.data[loc].items():
         a = ann.copy()
         DictTool.isub(a, ['img'])
         shape = LabelmeDict.gen_shape(json.dumps(a, ensure_ascii=False),
                                       a['points'],
                                       a['shape_type'],
                                       group_id=a['group_id'],
                                       flags=a['flags'])
         lmdict['shapes'].append(shape)
     f.write(lmdict, indent=2)
Exemplo n.º 2
0
        def add_shape(name, refdict, add_keys, drop_keys=('bbox', )):
            """ 生成一个标注框 """
            msgdict = {'category_name': name}
            msgdict.update(add_keys)
            DictTool.ior(msgdict, refdict)
            DictTool.isub(msgdict, drop_keys)
            bbox = [round_int(v * scale) for v in refdict['bbox']]

            if 'size' in msgdict:
                x = round_unit(msgdict['size'], 0.5)
                msgdict['size'] = round_int(
                    x) if (x * 10) % 10 < 1 else x  # 没有小数的时候,优先展示为11,而不是11.0
            if 'color' in msgdict:
                # 把color映射为直观的(r, g, b)
                # 这个pdf解析器获取的color,不一定精确等于原值,可能会有偏差,小一个像素
                v = msgdict['color']
                msgdict['color'] = (v // 256 // 256, (v // 256) % 256, v % 256)
            if 'origin' in msgdict:
                msgdict['origin'] = [round_int(v) for v in msgdict['origin']]

            sp = LabelmeDict.gen_shape(json.dumps(msgdict), bbox)
            shapes.append(sp)
Exemplo n.º 3
0
    def to_coco_gt_dict(self, categories=None):
        """ 将labelme转成 coco gt 标注的格式

        分两种大情况
        1、一种是raw原始数据转labelme标注后,首次转coco格式,这种编号等相关数据都可以重新生成
            raw_data --可视化--> labelme --转存--> coco
        2、还有种原来就是coco,转labelme修改标注后,又要再转回coco,这种应该尽量保存原始值
            coco --> labelme --手动修改--> labelme' --> coco'
            这种在coco转labelme时,会做一些特殊标记,方便后续转回coco
        3、 1, 2两种情况是可以连在一起,然后形成 labelme 和 coco 之间的多次互转的

        :param categories: 类别
            默认只设一个类别 {'id': 0, 'name': 'text', 'supercategory'}
            支持自定义,所有annotations的category_id
        :return: gt_dict
            注意,如果对文件顺序、ann顺序有需求的,请先自行操作self.data数据后,再调用该to_coco函数
            对image_id、annotation_id有需求的,需要使用CocoData进一步操作
        """
        from pyxllib.data.coco import CocoGtData

        if not categories:
            if 'categories' in self.extdata:
                # coco 转过来的labelme,存储有原始的 categories
                categories = self.extdata['categories']
            else:
                categories = [{'id': 0, 'name': 'text', 'supercategory': ''}]

        # 1 第一轮遍历:结构处理 jsonfile, lmdict --> data(image, shapes)
        img_id, ann_id, data = 0, 0, []
        for jsonfile, lmdict in self.rp2data.items():
            # 1.0 升级为字典类型
            lmdict = LabelmeDict.update_labelattr(lmdict, points=True)

            for sp in lmdict['shapes']:  # label转成字典
                sp['label'] = json.loads(sp['label'])

            # 1.1 找shapes里的image
            image = None
            # 1.1.1 xltype='image'
            for sp in filter(lambda x: x.get('xltype', None) == 'image',
                             lmdict['shapes']):
                image = DictTool.json_loads(sp['label'])
                if not image:
                    raise ValueError(sp['label'])
                # TODO 删除 coco_eval 等字段?
                del image['xltype']
                break
            # 1.1.2 shapes里没有图像级标注则生成一个
            if image is None:
                # TODO file_name 加上相对路径?
                image = CocoGtData.gen_image(-1, lmdict['imagePath'],
                                             lmdict['imageHeight'],
                                             lmdict['imageWidth'])
            img_id = max(img_id, image.get('id', -1))

            # 1.2 遍历shapes
            shapes = []
            for sp in lmdict['shapes']:
                label = sp['label']
                if 'xltype' not in label:
                    # 普通的标注框
                    d = sp['label'].copy()
                    # DictTool.isub_(d, '')
                    ann_id = max(ann_id, d.get('id', -1))
                    shapes.append(d)
                elif label['xltype'] == 'image':
                    # image,图像级标注数据;之前已经处理了,这里可以跳过
                    pass
                elif label['xltype'] == 'seg':
                    # seg,衍生的分割标注框,在转回coco时可以丢弃
                    pass
                else:
                    raise ValueError
            data.append([image, shapes])

        # 2 第二轮遍历:处理id等问题
        images, annotations = [], []
        for image, shapes in data:
            # 2.1 image
            if image.get('id', -1) == -1:
                img_id += 1
                image['id'] = img_id
            images.append(image)

            # 2.2 annotations
            for sp in shapes:
                sp['image_id'] = img_id
                if sp.get('id', -1) == -1:
                    ann_id += 1
                    sp['id'] = ann_id
                # 如果没有框类别,会默认设置一个。 (强烈建议外部业务功能代码自行设置好category_id)
                if 'category_id' not in sp:
                    sp['category_id'] = categories[0]['id']
                DictTool.isub(sp, ['category_name'])
                ann = CocoGtData.gen_annotation(**sp)
                annotations.append(ann)

        # 3 result
        gt_dict = CocoGtData.gen_gt_dict(images, annotations, categories)
        return gt_dict