数据集转换
1、xml2txt
import xml.etree.ElementTree as ET
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfile
class_names={'hat':0,'person':1}
TRAIN_RATIO = 80 def clear_hidden_files(path):"""清除隐藏文件:param path: 文件路径"""dir_list = os.listdir(path)for i in dir_list:abspath = os.path.join(os.path.abspath(path), i)if os.path.isfile(abspath):if i.startswith("._"):os.remove(abspath)else:clear_hidden_files(abspath)def convert(size, box):"""将标注框从 VOC 格式转换为 YOLO 格式:param size: 图像的宽和高:param box: 标注框的位置 (xmin, xmax, ymin, ymax):return: 转换后的标注框 (x, y, w, h)"""dw = 1. / size[0]dh = 1. / size[1]x = (box[0] + box[1]) / 2.0 - 1y = (box[2] + box[3]) / 2.0 - 1w = box[1] - box[0]h = box[3] - box[2]x = x * dww = w * dwy = y * dhh = h * dhreturn (x, y, w, h)def convert_annotation(image_id):"""将单个图像的 XML 标注文件转换为 YOLO 格式的 txt 文件:param image_id: 图像ID(文件名)"""in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' % image_id)out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' % 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').textcls = obj.find('name').textif cls not in class_names or int(difficult) == 1:continuecls_id = class_names[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')in_file.close()out_file.close()wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):os.mkdir(data_base_dir)
work_space_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_space_dir):os.mkdir(work_space_dir)
annotation_dir = os.path.join(work_space_dir, "Annotations/")
if not os.path.isdir(annotation_dir):os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_space_dir, "JPEGImages/")
if not os.path.isdir(image_dir):os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_space_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir)
for i in range(0, len(list_imgs)):path = os.path.join(image_dir, list_imgs[i])if os.path.isfile(path):image_path = image_dir + list_imgs[i]voc_path = list_imgs[i](nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))annotation_name = nameWithoutExtention + '.xml'annotation_path = os.path.join(annotation_dir, annotation_name)label_name = nameWithoutExtention + '.txt'label_path = os.path.join(yolo_labels_dir, label_name)prob = random.randint(1, 100)print("Probability: %d" % prob)if(prob < TRAIN_RATIO): if os.path.exists(annotation_path):train_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) copyfile(image_path, yolov5_images_train_dir + voc_path)copyfile(label_path, yolov5_labels_train_dir + label_name)else: if os.path.exists(annotation_path):test_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) copyfile(image_path, yolov5_images_test_dir + voc_path)copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()
2、xml2json
"""Author:DamonZhengFunction:xml2json(for labelme)Edition:1.0Date:2022.2.21
"""import argparse
import glob
import os
import xml.etree.ElementTree as ET
import json
from tqdm import tqdmdef parse_args():"""参数配置"""parser = argparse.ArgumentParser(description='xml2json')parser.add_argument('--raw_label_dir', help='the path of raw label', default='data/LabelmeData/VOC2007/Annotations')parser.add_argument('--pic_dir', help='the path of picture', default='data/LabelmeData/VOC2007/JPEGImages')parser.add_argument('--save_dir', help='the path of new label', default='data/coco/annotations')args = parser.parse_args()return argsdef read_xml_gtbox_and_label(xml_path):"""读取xml内容"""tree = ET.parse(xml_path)root = tree.getroot()size = root.find('size')width = int(size.find('width').text)height = int(size.find('height').text)depth = int(size.find('depth').text)points = []for obj in root.iter('object'):cls = obj.find('name').textpose = obj.find('pose').textxmlbox = obj.find('bndbox')xmin = float(xmlbox.find('xmin').text)xmax = float(xmlbox.find('xmax').text)ymin = float(xmlbox.find('ymin').text)ymax = float(xmlbox.find('ymax').text)box = [xmin, ymin, xmax, ymax]point = [cls, box]points.append(point)return points, width, heightdef main():"""主函数"""args = parse_args()labels = glob.glob(args.raw_label_dir + '/*.xml')for i, label_abs in tqdm(enumerate(labels), total=len(labels)):_, label = os.path.split(label_abs)label_name = label.rstrip('.xml')img_path = os.path.join(args.pic_dir, label_name + '.jpg')points, width, height = read_xml_gtbox_and_label(label_abs)json_str = {}json_str['version'] = '4.5.6'json_str['flags'] = {}shapes = []for i in range(len(points)):shape = {}shape['label'] = points[i][0]shape['points'] = [[points[i][1][0], points[i][1][1]],[points[i][1][0], points[i][1][3]],[points[i][1][2], points[i][1][3]],[points[i][1][2], points[i][1][1]]]shape['group_id'] = Noneshape['shape_type'] = 'polygon'shape['flags'] = {}shapes.append(shape)json_str['shapes'] = shapesjson_str['imagePath'] = img_pathjson_str['imageData'] = Nonejson_str['imageHeight'] = heightjson_str['imageWidth'] = widthwith open(os.path.join(args.save_dir, label_name + '.json'), 'w') as f:json.dump(json_str, f, indent=2)if __name__ == '__main__':main()
3、json2coco
import os
import json
import globdef polygon_to_bbox(polygon):x_coords = [point[0] for point in polygon]y_coords = [point[1] for point in polygon]x_min = min(x_coords)x_max = max(x_coords)y_min = min(y_coords)y_max = max(y_coords)width = x_max - x_minheight = y_max - y_minreturn [x_min, y_min, width, height]def convert_to_coco(input_folder, output_file):coco_data = {"images": [],"annotations": [],"categories": [],}category_map = {}annotation_id = 1image_id = 1categories = ['hat','person'] for i, category in enumerate(categories):coco_data['categories'].append({"id": i + 1,"name": category,"supercategory": "none"})category_map[category] = i + 1json_files = glob.glob(os.path.join(input_folder, "*.json"))for json_file in json_files:with open(json_file, 'r') as f:content = f.read().replace('\\', '\\\\') try:data = json.loads(content) print(data.keys()) except json.JSONDecodeError as e:print(f"Error parsing {json_file}: {e}")continue image_info = {"id": image_id,"file_name": data["imagePath"], "width": data["imageWidth"],"height": data["imageHeight"]}coco_data["images"].append(image_info)for ann in data["shapes"]:bbox = polygon_to_bbox(ann["points"])annotation_info = {"id": annotation_id,"image_id": image_id,"category_id": category_map[ann["label"]],"bbox": bbox,"area": bbox[2] * bbox[3], "iscrowd": 0}coco_data["annotations"].append(annotation_info)annotation_id += 1image_id += 1if not output_file.endswith(".json"):output_file += ".json"with open(output_file, 'w') as f:json.dump(coco_data, f, indent=4)
input_folder = 'data/LabelmeData/annotations/val'
output_file = 'data/coco/annotations'
convert_to_coco(input_folder, output_file)