不同数据集coco、voc格式互相转换python(json和xml)

目标:本博客会持续更新不同数据集格式转换,以适配各类检测任务;

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)

猜你喜欢

转载自blog.csdn.net/m0_63774211/article/details/131200859
今日推荐