目标:本博客会持续更新不同数据集格式转换,以适配各类检测任务;
1)coco_json2xml
输入:单个json,如instances_val2017.json
输出:多个xml
代码如下:
import os
import json
import cv2
from lxml import etree
import xml.etree.cElementTree as ET
import time
import pandas as pd
from tqdm import tqdm
from xml.dom.minidom import Document
anno = "instances_val2017.json"
xmldir = "train/"
with open(anno, 'r') as load_f:
f = json.load(load_f)
df_anno = pd.DataFrame(f['annotations'])
imgs = f['images']
cata={}
def createCate():
global cata
df_cate = f['categories']
for item in df_cate:
cata[item['id']]=item['name']
def json2xml():
global cata
for im in imgs:
filename = im['file_name']
height = im['height']
img_id = im['id']
width = im['width']
doc = Document()
annotation = doc.createElement('annotation')
doc.appendChild(annotation)
filenamedoc = doc.createElement("filename")
annotation.appendChild(filenamedoc)
filename_txt=doc.createTextNode(filename)
filenamedoc.appendChild(filename_txt)
size = doc.createElement("size")
annotation.appendChild(size)
widthdoc = doc.createElement("width")
size.appendChild(widthdoc)
width_txt = doc.createTextNode(str(width))
widthdoc.appendChild(width_txt)
heightdoc = doc.createElement("height")
size.appendChild(heightdoc)
height_txt = doc.createTextNode(str(height))
heightdoc.appendChild(height_txt)
annos = df_anno[df_anno["image_id"].isin([img_id])]
for index, row in annos.iterrows():
bbox = row["bbox"]
category_id = row["category_id"]
cate_name = cata[category_id]
object = doc.createElement('object')
annotation.appendChild(object)
name = doc.createElement('name')
object.appendChild(name)
name_txt = doc.createTextNode(cate_name)
name.appendChild(name_txt)
pose = doc.createElement('pose')
object.appendChild(pose)
pose_txt = doc.createTextNode('Unspecified')
pose.appendChild(pose_txt)
truncated = doc.createElement('truncated')
object.appendChild(truncated)
truncated_txt = doc.createTextNode('0')
truncated.appendChild(truncated_txt)
difficult = doc.createElement('difficult')
object.appendChild(difficult)
difficult_txt = doc.createTextNode('0')
difficult.appendChild(difficult_txt)
bndbox = doc.createElement('bndbox')
object.appendChild(bndbox)
xmin = doc.createElement('xmin')
bndbox.appendChild(xmin)
xmin_txt = doc.createTextNode(str(int(bbox[0])))
xmin.appendChild(xmin_txt)
ymin = doc.createElement('ymin')
bndbox.appendChild(ymin)
ymin_txt = doc.createTextNode(str(int(bbox[1])))
ymin.appendChild(ymin_txt)
xmax = doc.createElement('xmax')
bndbox.appendChild(xmax)
xmax_txt = doc.createTextNode(str(int(bbox[0]+bbox[2])))
xmax.appendChild(xmax_txt)
ymax = doc.createElement('ymax')
bndbox.appendChild(ymax)
ymax_txt = doc.createTextNode(str(int(bbox[1]+bbox[3])))
ymax.appendChild(ymax_txt)
xmlpath = os.path.join(xmldir,filename.replace('.jpg','.xml'))
f = open(xmlpath, "w")
f.write(doc.toprettyxml(indent=" "))
f.close()
createCate()
json2xml()
2)VOCXML_to_COCOJSON
输入:多个xml
输出:单个json
代码如下:
import os
import glob
import json
import shutil
import numpy as np
import xml.etree.ElementTree as ET
path2 = "."
START_BOUNDING_BOX_ID = 1
def get(root, name):
return root.findall(name)
def get_and_check(root, name, length):
vars = root.findall(name)
if len(vars) == 0:
raise NotImplementedError('Can not find %s in %s.' % (name, root.tag))
if length > 0 and len(vars) != length:
raise NotImplementedError('The size of %s is supposed to be %d, but is %d.' % (name, length, len(vars)))
if length == 1:
vars = vars[0]
return vars
def convert(xml_list, json_file):
json_dict = {"images": [], "type": "instances", "annotations": [], "categories": []}
categories = pre_define_categories.copy()
bnd_id = START_BOUNDING_BOX_ID
all_categories = {}
for index, line in enumerate(xml_list):
# print("Processing %s"%(line))
xml_f = line
tree = ET.parse(xml_f)
root = tree.getroot()
xml = os.path.split(xml_f)[-1].split(".")[0]
img = xml+".jpg"
filename = img
image_id = 20210000001 + index
size = get_and_check(root, 'size', 1)
width = int(get_and_check(size, 'width', 1).text)
height = int(get_and_check(size, 'height', 1).text)
image = {'file_name': filename, 'height': height, 'width': width, 'id': image_id}
json_dict['images'].append(image)
for obj in get(root, 'object'):
category = get_and_check(obj, 'name', 1).text
if category in all_categories:
all_categories[category] += 1
else:
all_categories[category] = 1
if category not in categories:
if only_care_pre_define_categories:
continue
new_id = len(categories) + 1
print(
"[warning] category '{}' not in 'pre_define_categories'({}), create new id: {} automatically".format(
category, pre_define_categories, new_id))
categories[category] = new_id
category_id = categories[category]
bndbox = get_and_check(obj, 'bndbox', 1)
xmin = int(float(get_and_check(bndbox, 'xmin', 1).text))
ymin = int(float(get_and_check(bndbox, 'ymin', 1).text))
xmax = int(float(get_and_check(bndbox, 'xmax', 1).text))
ymax = int(float(get_and_check(bndbox, 'ymax', 1).text))
assert (xmax > xmin), "xmax <= xmin, {}".format(line)
assert (ymax > ymin), "ymax <= ymin, {}".format(line)
o_width = abs(xmax - xmin)
o_height = abs(ymax - ymin)
ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id':
image_id, 'bbox': [xmin, ymin, o_width, o_height],
'category_id': category_id, 'id': bnd_id, 'ignore': 0,
'segmentation': []}
json_dict['annotations'].append(ann)
bnd_id = bnd_id + 1
for cate, cid in categories.items():
cat = {'supercategory': 'none', 'id': cid, 'name': cate}
json_dict['categories'].append(cat)
json_fp = open(json_file, 'w')
json_str = json.dumps(json_dict)
json_fp.write(json_str)
json_fp.close()
print("------------create {} done--------------".format(json_file))
print("find {} categories: {} -->>> your pre_define_categories {}: {}".format(len(all_categories),
all_categories.keys(),
len(pre_define_categories),
pre_define_categories.keys()))
print("category: id --> {}".format(categories))
print(categories.keys())
print(categories.values())
if __name__ == '__main__':
classes = ['head']
pre_define_categories = {}
for i, cls in enumerate(classes):
pre_define_categories[cls] = i + 1
# pre_define_categories = {'a1': 1, 'a3': 2, 'a6': 3, 'a9': 4, "a10": 5}
only_care_pre_define_categories = True
train_ratio = 0.9
save_json_train = 'head_train2021.json'
save_json_val = 'head_val2021.json'
xml_dir = "./Annotations1"
xml_list = glob.glob(xml_dir + "/*.xml")
xml_list = np.sort(xml_list)
np.random.seed(100)
np.random.shuffle(xml_list)
train_num = int(len(xml_list) * train_ratio)
xml_list_train = xml_list[:train_num]
xml_list_val = xml_list[train_num:]
convert(xml_list_train, save_json_train)
convert(xml_list_val, save_json_val)
if os.path.exists(path2 + "/images/train2021"):
shutil.rmtree(path2 + "/images/train2021")
os.makedirs(path2 + "/images/train2021")
if os.path.exists(path2 + "/images/val2021"):
shutil.rmtree(path2 + "/images/val2021")
os.makedirs(path2 + "/images/val2021")
f1 = open("train.txt", "w")
for xml in xml_list_train:
xml = os.path.split(xml)[-1].split(".")[0]
img = xml+".jpg"
f1.write(img + "\n")
shutil.copyfile(path2+"/JPEGImages/"+img, path2 + "/images/train2021/" + img)
f2 = open("test.txt", "w")
for xml in xml_list_val:
xml = os.path.split(xml)[-1].split(".")[0]
img = xml+".jpg"
f2.write(img + "\n")
shutil.copyfile(path2+"/JPEGImages/"+img, path2 + "/images/val2021/" + img)
f1.close()
f2.close()
print("-------------------------------")
print("train number:", len(xml_list_train))
print("val number:", len(xml_list_val))
2)json2xmlByOpjectName
输入:单个json
输出:多个xml
注意点需要手动输入类别名称
代码如下:
import os
import json
import cv2
from lxml import etree
import xml.etree.cElementTree as ET
import time
import pandas as pd
from tqdm import tqdm
from xml.dom.minidom import Document
anno = "instances_val2017.json"
xml_dir = "test/"
# dttm = time.strftime("%Y%m%d%H%M%S", time.localtime())
# if os.path.exists(xml_dir):
# os.rename(xml_dir,xml_dir+dttm)
# os.mkdir(xml_dir)
import json
with open(anno, 'r') as load_f:
f = json.load(load_f)
df_anno = pd.DataFrame(f['annotations'])
imgs = f['images']
cata={}
nameList=[ 'bench', 'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
'sandwich', 'orange', 'broccoli','carrot', 'hot dog', 'pizza', 'donut', 'laptop', 'mouse', 'remote', 'keyboard', 'cell phone', 'book', 'clock', 'vase', 'scissors', 'hair drier', 'toothbrush']
#nameNum={ 'bench':0, 'backpack':0, 'umbrella':0, 'handbag':0, 'tie':0, 'suitcase':0, 'frisbee':0, 'skis':0, 'snowboard':0, 'sports ball':0, 'kite':0, 'baseball bat':0, 'baseball glove':0,
# 'skateboard':0, 'surfboard':0, 'tennis racket':0, 'bottle':0, 'wine glass':0, 'cup':0, 'fork':0, 'knife':0, 'spoon':0, 'bowl':0, 'banana':0, 'apple':0,
#'sandwich':0, 'orange':0, 'broccoli':0,'carrot':0, 'hot dog':0, 'pizza':0, 'donut':0, 'laptop':0, 'mouse':0, 'remote':0, 'keyboard':0, 'cell phone':0, 'book':0, 'clock':0, 'vase':0, 'scissors':0, 'hair drier':0, 'toothbrush':0}
#imageSum=0
flag=0
def createCate():
global cata
df_cate = f['categories']
for item in df_cate:
cata[item['id']]=item['name']
def json2xml():
global cata
global flag
#global imageSum
for im in imgs:
#imageSum = imageSum+1
flag = 0
filename = im['file_name']
height = im['height']
img_id = im['id']
width = im['width']
doc = Document()
annotation = doc.createElement('annotation')
doc.appendChild(annotation)
filenamedoc = doc.createElement("filename")
annotation.appendChild(filenamedoc)
filename_txt=doc.createTextNode(filename)
filenamedoc.appendChild(filename_txt)
size = doc.createElement("size")
annotation.appendChild(size)
widthdoc = doc.createElement("width")
size.appendChild(widthdoc)
width_txt = doc.createTextNode(str(width))
widthdoc.appendChild(width_txt)
heightdoc = doc.createElement("height")
size.appendChild(heightdoc)
height_txt = doc.createTextNode(str(height))
heightdoc.appendChild(height_txt)
annos = df_anno[df_anno["image_id"].isin([img_id])]
for index, row in annos.iterrows():
bbox = row["bbox"]
category_id = row["category_id"]
cate_name = cata[category_id]
if cate_name not in nameList:
print(cate_name+",don`t in namelis")
continue
flag=1
#nameNum[cate_name]=nameNum[cate_name]+1
object = doc.createElement('object')
annotation.appendChild(object)
name = doc.createElement('name')
object.appendChild(name)
name_txt = doc.createTextNode(cate_name)
name.appendChild(name_txt)
pose = doc.createElement('pose')
object.appendChild(pose)
pose_txt = doc.createTextNode('Unspecified')
pose.appendChild(pose_txt)
truncated = doc.createElement('truncated')
object.appendChild(truncated)
truncated_txt = doc.createTextNode('0')
truncated.appendChild(truncated_txt)
difficult = doc.createElement('difficult')
object.appendChild(difficult)
difficult_txt = doc.createTextNode('0')
difficult.appendChild(difficult_txt)
bndbox = doc.createElement('bndbox')
object.appendChild(bndbox)
xmin = doc.createElement('xmin')
bndbox.appendChild(xmin)
xmin_txt = doc.createTextNode(str(int(bbox[0])))
xmin.appendChild(xmin_txt)
ymin = doc.createElement('ymin')
bndbox.appendChild(ymin)
ymin_txt = doc.createTextNode(str(int(bbox[1])))
ymin.appendChild(ymin_txt)
xmax = doc.createElement('xmax')
bndbox.appendChild(xmax)
xmax_txt = doc.createTextNode(str(int(bbox[0]+bbox[2])))
xmax.appendChild(xmax_txt)
ymax = doc.createElement('ymax')
bndbox.appendChild(ymax)
ymax_txt = doc.createTextNode(str(int(bbox[1]+bbox[3])))
ymax.appendChild(ymax_txt)
if flag==1:
xml_path = os.path.join(xml_dir,filename.replace('.jpg','.xml'))
f = open(xml_path, "w")
f.write(doc.toprettyxml(indent=" "))
f.close()
createCate()
json2xml()
#print('imagenum:',imageSum)
#print(nameNum)