此代码可以将xml转为coco数据集中的json,json参考easydata导出的格式。
# -*- coding: utf-8 -*-
# @Time : 2022/7/19 21:47
# @Author : lisihong
# @File : voc2coco.py
# for object detection
#@ 修改说明:
# 1、完全按照easydata,coco数据集的json序号来;
# 2、image_id=1,在coco_json中"images"下的"id"从1开始;
# 3、category_item_id = -1,在coco_json中"categories"下的"id"从0开始;
# 4、annotation_id = 0 ,标签的id,在coco_json中从1开始,统计打了多少个标签不是种类。
import xml.etree.ElementTree as ET
import os
import json
coco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []
category_set = dict()
image_set = set()
category_item_id = -1
image_id = 1
annotation_id = 0
def addCatItem(name):
global category_item_id
category_item = dict()
category_item['supercategory'] = 'none'
category_item_id += 1
category_item['id'] = category_item_id
category_item['name'] = name
coco['categories'].append(category_item)
category_set[name] = category_item_id
return category_item_id
def addImgItem(file_name, size):
global image_id
if file_name is None:
raise Exception('Could not find filename tag in xml file.')
if size['width'] is None:
raise Exception('Could not find width tag in xml file.')
if size['height'] is None:
raise Exception('Could not find height tag in xml file.')
img_id = "%04d" % image_id
image_id += 1
image_item = dict()
image_item['id'] = int(img_id)
# image_item['id'] = image_id
image_item['file_name'] = file_name
image_item['width'] = size['width']
image_item['height'] = size['height']
coco['images'].append(image_item)
image_set.add(file_name)
return image_id - 1
def addAnnoItem(object_name, image_id, category_id, bbox):
global annotation_id
annotation_item = dict()
annotation_item['segmentation'] = []
seg = []
# bbox[] is x,y,w,h
# left_top
seg.append(bbox[0])
seg.append(bbox[1])
# left_bottom
seg.append(bbox[0])
seg.append(bbox[1] + bbox[3])
# right_bottom
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1] + bbox[3])
# right_top
seg.append(bbox[0] + bbox[2])
seg.append(bbox[1])
annotation_item['segmentation'].append(seg)
annotation_item['area'] = bbox[2] * bbox[3]
annotation_item['iscrowd'] = 0
annotation_item['ignore'] = 0
annotation_item['image_id'] = image_id
annotation_item['bbox'] = bbox
annotation_item['category_id'] = category_id
annotation_id += 1
annotation_item['id'] = annotation_id
coco['annotations'].append(annotation_item)
def parseXmlFiles(xml_path):
for f in os.listdir(xml_path):
if not f.endswith('.xml'):
continue
bndbox = dict()
size = dict()
current_image_id = None
current_category_id = None
file_name = None
size['width'] = None
size['height'] = None
size['depth'] = None
xml_file = os.path.join(xml_path, f)
# print(xml_file)
tree = ET.parse(xml_file)
root = tree.getroot()
if root.tag != 'annotation':
raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))
# elem is , , ,
从easydata导出的json格式如下:
1、"images"下的’‘id’‘从1开始;
2、"annotations"中的"image_id"就是1、中的id;
3、"annotations"中的’‘id’'从1开始,统计一共打了多少标签;
4、"annotations"中的"category_id"从0开始,是下文中的类别标签;
5、“categories"中的"id"是4、中的"category_id”,从0开始。
下图是生成的json代码
生成的json:
一、"images"下的’‘id’‘从1开始;
二、"annotations"中的"image_id"就是一、中的id;
三、"annotations"中的’‘id’'从1开始,统计一共打了多少标签;
四、"annotations"中的"category_id"从0开始,是下文中的类别标签;
五、“categories"中的"id"是、中的"category_id”,从0开始。



