json格式与xml格式转换为Yolov5训练标签格式
1、json格式转yolov5标签格式# 实现json文件yolov5训练的txt文件# 注意:图像的宽高需要自定义import jsonimport osdef 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]cen
·
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
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐



所有评论(0)