目标检测 中 txt转xml完整代码,适应各种图片后缀 和 xml转coco

1.xml转coco的完整代码:

import os
import json
import xml.etree.ElementTree as ET
import glob
 
 
def get_and_check(root, name, length, cast_type=int):
    vars = root.findall(name)
    if length > 0 and len(vars) != length:
        raise ValueError(
            "The size of %s is supposed to be %d, but is %d."
            % (name, length, len(vars))
        )
    return [cast_type(var.text.strip()) for var in vars if var.text]
 
 
def get_categories(xml_files):
    classes_names = set()
    for xml_file in xml_files:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        for obj in root.findall("object"):
            classes_names.add(get_and_check(obj, "name", 1)[0])
    classes_names = list(classes_names)
    classes_names.sort()
    return {name: i for i, name in enumerate(classes_names)}
 
 
def generate_label_file(xml_files, json_file, categories=None):
    if categories is None:
        categories = get_categories(xml_files)
    json_dict = {"images": [], "annotations": [], "categories": []}
    bnd_id = 1
    image_id = 1
    for xml_file in xml_files:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        filename = get_and_check(root, "filename", 1, cast_type=str)[0]
 
        # 直接获取尺寸信息的子元素并转换为整数
        width = int(root.find("size/width").text)
        height = int(root.find("size/height").text)
 
        image = {
            "file_name": filename,
            "height": height,
            "width": width,
            "id": image_id,
        }
        json_dict["images"].append(image)
 
        for obj in root.findall("object"):
            category = get_and_check(obj, "name", 1, cast_type=str)[0]
            if category not in categories:
                print(f"Warning: {category} not in categories. Skipping object.")
                continue
            bndbox = obj.find("bndbox")
            xmin = get_and_check(bndbox, "xmin", 1, cast_type=int)[0] - 1
            ymin = get_and_check(bndbox, "ymin", 1, cast_type=int)[0] - 1
            xmax = get_and_check(bndbox, "xmax", 1, cast_type=int)[0]
            ymax = get_and_check(bndbox, "ymax", 1, cast_type=int)[0]
            category_id = categories[category]
            ann = {
                "id": bnd_id,
                "image_id": image_id,
                "category_id": category_id,
                "iscrowd": 0,
                "area": (xmax - xmin) * (ymax - ymin),
                "bbox": [xmin, ymin, xmax - xmin, ymax - ymin],
                "segmentation": [],
                "ignore": 0,
            }
            json_dict["annotations"].append(ann)
            bnd_id += 1
        image_id += 1
 
    for cate, cid in categories.items():
        cat = {"supercategory": "none", "id": cid, "name": cate}
        json_dict["categories"].append(cat)
 
    os.makedirs(os.path.dirname(json_file), exist_ok=True)
    with open(json_file, "w") as json_fp:
        json.dump(json_dict, json_fp, indent=4)
 
 
if __name__ == "__main__":
    xml_path = "xml/test"  # XML文件所在文件夹路径
    xml_files = glob.glob(os.path.join(xml_path, "*.xml"))
    json_file = "coco/instances_test2017.json"  # 生成的JSON文件保存路径
    categories = {
        "cat": 1,
        "dog": 2,
        "people": 3,
    }  # 预先定义的类别字典
    generate_label_file(xml_files, json_file, categories)
    print(f"JSON file {json_file} has been created.")

1.1需要修改的地方
在这里插入图片描述

2.txt转xml完整代码,适应各种图片后缀:

# coding:utf-8
from xml.dom import minidom

import cv2,os,sys,shutil,tqdm
import numpy as np

def create_xml_test(xml_path,img_path,txt_path):
    # 新建xml文档对象
    xml = minidom.Document()
    # 创建第一个节点,第一个节点就是根节点了
    root = xml.createElement('annotation')
    xml.appendChild(root)

    # 那么给根节点再创建一个folder节点
    folder_node = xml.createElement('folder')
    root.appendChild(folder_node)
    text = xml.createTextNode('JPEGImages')
    folder_node.appendChild(text)

    # 那么给根节点再创建一个filename节点
    filename_node = xml.createElement('filename')
    root.appendChild(filename_node)
    text = xml.createTextNode(img_path.split('/')[-1])
    filename_node.appendChild(text)

    # 那么给根节点再创建一个path节点
    path_node = xml.createElement('path')
    root.appendChild(path_node)
    text = xml.createTextNode(img_path)
    path_node.appendChild(text)

    # 那么给根节点再创建一个source节点
    source_node = xml.createElement('source')
    root.appendChild(source_node)
    database_node = xml.createElement('database')
    source_node.appendChild(database_node)
    text = xml.createTextNode('Unknown')
    database_node.appendChild(text)

    # 那么给根节点再创建一个size节点
    img = cv2.imread(img_path)
    try:
        H, W, C = img.shape
    except Exception as e:
        print("无法获取图像形状:", e)
        print("图像内容:", img_path)

    size_node = xml.createElement('size')
    root.appendChild(size_node)
    #width_node
    width_node = xml.createElement('width')
    size_node.appendChild(width_node)
    text = xml.createTextNode('%d'%W)
    width_node.appendChild(text)
    #height_node
    height_node = xml.createElement('height')
    size_node.appendChild(height_node)
    text = xml.createTextNode('%d'%H)
    height_node.appendChild(text)
    #depth_node
    depth_node = xml.createElement('depth')
    size_node.appendChild(depth_node)
    text = xml.createTextNode('%d'%C)
    depth_node.appendChild(text)

    # 那么给根节点再创建一个segmented节点
    segmented_node = xml.createElement('segmented')
    root.appendChild(segmented_node)
    text = xml.createTextNode('0')
    segmented_node.appendChild(text)

    ## 增加 object 节点
    txt_lines = open(txt_path,'r').readlines()
    for line in txt_lines:
        line = line.strip()
        line_lst = line.split(' ')
        if len(line_lst)!=5:
            continue
        class_id = int(line_lst[0])
        class_name = CLASSES[class_id]
        x_cen = float(line_lst[1]) * img.shape[1]
        y_cen = float(line_lst[2]) * img.shape[0]
        w = float(line_lst[3]) * img.shape[1]
        h = float(line_lst[4]) * img.shape[0]
        x_min = int(x_cen-w/2.0)
        y_min = int(y_cen-h/2.0)
        x_max = int(x_cen+w/2.0)
        y_max = int(y_cen+h/2.0)

        object_node = xml.createElement('object')
        root.appendChild(object_node)
        #name
        name_node = xml.createElement('name')
        object_node.appendChild(name_node)
        text = xml.createTextNode(class_name)
        name_node.appendChild(text)
        #pose
        pose_node = xml.createElement('pose')
        object_node.appendChild(pose_node)
        text = xml.createTextNode('Unspecified')
        pose_node.appendChild(text)
        #truncated
        truncated_node = xml.createElement('truncated')
        object_node.appendChild(truncated_node)
        text = xml.createTextNode('0')
        truncated_node.appendChild(text)
        #difficult
        difficult_node = xml.createElement('difficult')
        object_node.appendChild(difficult_node)
        text = xml.createTextNode('0')
        difficult_node.appendChild(text)

        #bndbox
        bndbox_node = xml.createElement('bndbox')
        object_node.appendChild(bndbox_node)

        xmin_node = xml.createElement('xmin')
        bndbox_node.appendChild(xmin_node)
        text = xml.createTextNode('%d' % x_min)
        xmin_node.appendChild(text)

        ymin_node = xml.createElement('ymin')
        bndbox_node.appendChild(ymin_node)
        text = xml.createTextNode('%d' % y_min)
        ymin_node.appendChild(text)

        xmax_node = xml.createElement('xmax')
        bndbox_node.appendChild(xmax_node)
        text = xml.createTextNode('%d' % x_max)
        xmax_node.appendChild(text)

        ymax_node = xml.createElement('ymax')
        bndbox_node.appendChild(ymax_node)
        text = xml.createTextNode('%d'%y_max)
        ymax_node.appendChild(text)



    with open(xml_path, "w", encoding="utf8") as outfile:
        outfile.write(xml.toprettyxml())

if __name__ == '__main__':
    CLASSES = ['smoke','fire']
    img_root = r"/gpfs/home/qixinggroup/newdata-07-16/data/images/train/"
    img_list = os.listdir(img_root)
    img_list = [img_root + v for v in img_list if (v.endswith('.jpg') or v.endswith('.png') or v.endswith('.jpeg') or v.endswith('.PNG') or v.endswith('.JPG') or v.endswith('.JPEG'))]
    # img_list = [img_root + '001_img11615.jpg']
    #"C:/Users/29269/Desktop/simAM/train/Annotations/"
    xml_root= r"/gpfs/home/qixinggroup/newdata-07-16/data/Annotations/train/"
    if os.path.exists(xml_root) is False:
        os.makedirs(xml_root)

    for img_path in tqdm.tqdm(img_list):
        txt_path = img_path.replace('/images/','/labels/').replace('.jpg','.txt').replace('.png','.txt').replace('.PNG','.txt').replace('.JPG','.txt').replace('.jpeg','.txt').replace('.JPEG','.txt')
        if os.path.exists(txt_path) is False:
            continue
        if os.path.exists(txt_path) is True:
            print(os.path.exists(txt_path) )
        xml_path = img_path.replace('/images/','/Annotations/').replace('.jpg','.xml').replace('.png','.xml').replace('.PNG','.xml').replace('.JPG','.xml').replace('.jpeg','.xml').replace('.JPEG','.xml')

        create_xml_test(xml_path=xml_path,img_path=img_path,txt_path=txt_path)

2.1需要修改的地方如下:在这里插入图片描述

2.2文件的路径格式需要保持如下才能正常的运行:
在这里插入图片描述

3.参考资料:
https://blog.csdn.net/weixin_53035684/article/details/140838377

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值