【Code】格式转换 voc2yolo()

Published: by Creative Commons Licence

直接上代码

import xml.etree.ElementTree as ET
import os
  • 分类的集合,类别和标号的桥梁
  • 文件路径
classes = ["class_0", "class_1", "class_2", "class_3", "class_4"]
file_paths = ['path_0', 'path_1', 'path_2']
  • 转换成相对坐标(中心x坐标,中心y坐标,宽,高)
def convert(size, box):
    dw = 1./size[0]
    dh = 1./size[1]
    x = (box[0] + box[1])/2.0
    y = (box[2] + box[3])/2.0
    w = box[1] - box[0]
    h = box[3] - box[2]
    x = x * dw
    w = w * dw
    y = y * dh
    h = h * dh
    return (x,y,w,h)
  • 读取xml文件,新建并写入txt文件
def convert_annotation(file_path, image_id):
    in_file = open('%s/%s.xml'%(file_path, image_id))
    out_file = open('%s/%s.txt'%(file_path, image_id), 'w')
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    for obj in root.iter('object'):
        difficult = obj.find('difficult').text
        cls = obj.find('name').text
        if cls not in classes or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')
        b = (float(xmlbox.find('xmin').text), 
            float(xmlbox.find('xmax').text), 
            float(xmlbox.find('ymin').text), 
            float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  • 提取出所有的图片编号,为了后期作为文件名以及循环做准备。
def img_id_set(path):
    imgids = []
    file_type = '.xml'
    for root, dir, files in os.walk(path):
        for file in files:
            # 找出以'.xml'为后缀的文件,将其后缀删除,并存入返回值imgids中
            if file.endswith(file_type):
                f_name = file.replace(file_type, '')
                imgids.append(f_name)
    return imgids
  • 格式转换函数
def voc2yolo(path_set):
    for path in path_set:
        for img_id in img_id_set(path):
            convert_annotation(file_path=path, image_id=img_id)
  • 程序运行
voc2yolo(path_set=file_paths)