json格式与xml格式转换为Yolov5训练标签格式

1、json格式转yolov5标签格式

# 实现json文件yolov5训练的txt文件
# 注意:图像的宽高需要自定义


import json
import os


def convert(img_size, box):
    x1 = box[0]
    y1 = box[1]
    x2 = box[2]
    y2 = box[3]

    # 转换并归一化
    center_x = (x1 + x2) * 0.5 / img_size[0]
    center_y = (y1 + y2) * 0.5 / img_size[1]
    w = abs((x2 - x1)) * 1.0 / img_size[0]
    h = abs((y2 - y1)) * 1.0 / img_size[1]

    return (center_x, center_y, w, h)



def decode_json(save_path, jsonfloder_path, json_name, classes):
    txt_name = save_path + json_name[0:-5] + '.txt'
    # txt保存位置

    
    json_path = os.path.join(json_folder_path, json_name)
    data = json.load(open(json_path, 'r'))

    img_w = 1280
    img_h = 720
    with open(txt_name, 'w') as txt_file:  # te files
        for i in data['labels']:
            if i['box2d']:  # 仅适用矩形框标注
                x1 = float(i['box2d']['x1'])
                y1 = float(i['box2d']['y1'])
                x2 = float(i['box2d']['x2'])
                y2 = float(i['box2d']['y2'])
                if x1 < 0 or x2 < 0 or y1 < 0 or y2 < 0:
                    continue
                else:
                    bb = (x1, y1, x2, y2)
                    bbox = convert((img_w, img_h), bb)
                
                cls = i['category']  # 得到当前label的类别
                
                # 转换成训练模式读取的标签
                cls_id = classes.index(cls)  # 位于定义类别索引位置
                
                # 保存
                txt_file.write(str(cls_id) + ' ' +" ".join([str(a) for a in bbox])+"\n")  # 生成格式0 cx,cy,w,h
            
       


if __name__ == "__main__":

    # 数据的类别
    classes_train = ['pedestrian']   # 修改1,类别

    json_folder_path = 'path_1/'  # 修改2,json文件夹路径,
    save_path = 'path_2/'    # 修改3,保存位置

    json_names = os.listdir(json_folder_path)  # file name
    
    # 遍历所有json文件
    for json_name in json_names:  # output all files
        if json_name[-5:] == '.json':  # just work for json files
            decode_json(save_path, json_folder_path, json_name, classes_train)


2、xml格式转yolov5标签格式

# 实现xml格式转yolov5格式


import xml.etree.ElementTree as ET
import os


# box [xmin,ymin,xmax,ymax]
def convert(size, box):
    x_center = (box[2] + box[0]) / 2.0
    y_center = (box[3] + box[1]) / 2.0
    # 归一化
    x = x_center / size[0]
    y = y_center / size[1]
    # 求宽高并归一化
    w = (box[2] - box[0]) / size[0]
    h = (box[3] - box[1]) / size[1]
    return (x, y, w, h)


def convert_annotation(xml_paths, yolo_paths, classes):
    xml_files = os.listdir(xml_paths)
    # 生成无序文件列表
    print(f'xml_files:{
      
      xml_files}')
    for file in xml_files:
        xml_file_path = os.path.join(xml_paths, file)
        yolo_txt_path = os.path.join(yolo_paths, file.split(".")[0]
                                     + ".txt")
        tree = ET.parse(xml_file_path)
        root = tree.getroot()
        size = root.find("size")
        # 获取xml的width和height的值
        w = int(size.find("width").text)
        h = int(size.find("height").text)
        # object标签可能会存在多个,所以要迭代
        with open(yolo_txt_path, 'w') as f:
            for obj in root.iter("object"):
                difficult = obj.find("difficult").text
                # 种类类别
                cls = obj.find("name").text
                if cls not in classes or difficult == 1:
                    continue
                # 转换成训练模式读取的标签
                cls_id = classes.index(cls)
                xml_box = obj.find("bndbox")
                box = (float(xml_box.find("xmin").text), float(xml_box.find("ymin").text),
                       float(xml_box.find("xmax").text), float(xml_box.find("ymax").text))
                boxex = convert((w, h), box)
                # yolo标准格式类别 x_center,y_center,width,height
                f.write(str(cls_id) + " " + " ".join([str(s) for s in boxex]) + '\n')


if __name__ == "__main__":
    # 数据的类别
    classes_train = ['pedestrian']   # 修改1,类别
    
    # xml存储地址
    xml_dir = "path_1/"  # 修改2,读取位置
    
    # yolo存储地址
    yolo_txt_dir = "path_2/"   # 修改3,保存位置
    
    # voc转yolo
    convert_annotation(xml_paths=xml_dir, yolo_paths=yolo_txt_dir,
                       classes=classes_train)


3、转换结果如下:(center_x, center_y, w, h)+ 归一化

0 0.13672086562500002 0.42883250209276375 0.0518377734375 0.2381447458144725
0 0.9693835771642189 0.3827724250266623 0.0372473316090625 0.1542235472755468
0 0.033346999609375004 0.43807428263888887 0.040952453906250005 0.22881371805555556
0 0.8286290180594396 0.36559139469421237 0.026519851116625227 0.10421836228287841

猜你喜欢

转载自blog.csdn.net/weixin_45679938/article/details/121938179
今日推荐