【图像标签转换】XML转为TXT图像数据集标签

引言

该脚本用于将包含对象标注的 XML 文件转换为 YOLO(You Only Look Once)对象检测格式的 TXT 文件。脚本读取 XML 文件,提取对象信息,规范化边界框坐标,并将数据写入相应的 TXT 文件。此外,它还生成一个 classes.txt 文件,列出所有对象类别。

效果:

环境和依赖

  • Python 3.x
  • 库:os, xml.etree.ElementTree

目录结构

  • 输入目录:包含对象标注的 XML 文件。
  • 输出目录 :将包含转换后的 TXT 文件和 classes.txt 文件。

目录

[1. 引入必要的库](#1. 引入必要的库)

[2. 定义输入和输出目录,以及类别列表](#2. 定义输入和输出目录,以及类别列表)

[3. 获取所有 XML 文件的文件名](#3. 获取所有 XML 文件的文件名)

[4. 获取所有分类](#4. 获取所有分类)

[5. 转换坐标到 YOLO 格式](#5. 转换坐标到 YOLO 格式)

[6. 读取 XML 文件并转换为 TXT 文件](#6. 读取 XML 文件并转换为 TXT 文件)

[7. 主函数](#7. 主函数)

完整程序


1. 引入必要的库

  • os 用于处理文件和目录操作。

  • xml.etree.ElementTree 用于解析 XML 文件

    import os
    import xml.etree.ElementTree as ET

2. 定义输入和输出目录,以及类别列表

复制代码
input_dir = r'D:/lenovo/Archie/shujukuochongv1.0/xmlall1'
out_dir = r'D:/lenovo/Archie/shujukuochongv1.0/txtall1'
class_list = ['1','2','3','4','5','6','7','8','9']
  • input_dir 是存放 XML 文件的目录。
  • out_dir 是保存转换后 TXT 文件的目录。
  • class_list 是初始定义的类别名列表。

3. 获取所有 XML 文件的文件名

遍历输入目录,获取所有 XML 文件的文件名(不带扩展名)。

复制代码
def file_name(input_dir):
    F = []
    for root, dirs, files in os.walk(input_dir):
        for file in files:
            if os.path.splitext(file)[1] == '.xml':
                t = os.path.splitext(file)[0]
                F.append(t)  # 将所有的文件名添加到 F 列表中
    return F  # 返回 F 列表

4. 获取所有分类

解析每个 XML 文件,获取对象的类别,并添加到类别列表中(跳过 difficult 属性为 1 的对象)。

复制代码
def get_class(filelist):
    for i in filelist:
        f_dir = input_dir + "\\" + i + ".xml"
        in_file = open(f_dir, encoding='UTF-8')
        filetree = ET.parse(in_file)
        in_file.close()
        root = filetree.getroot()
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in class_list and int(difficult) == 0:
                class_list.append(cls)

5. 转换坐标到 YOLO 格式

将 XML 文件中的像素坐标转换为 YOLO 格式的归一化坐标。

复制代码
def ConverCoordinate(imgshape, bbox):
    xmin, xmax, ymin, ymax = bbox
    width = imgshape[0]
    height = imgshape[1]
    dw = 1. / width
    dh = 1. / height
    x = (xmin + xmax) / 2.0
    y = (ymin + ymax) / 2.0
    w = xmax - xmin
    h = ymax - ymin

    x = x * dw
    y = y * dh
    w = w * dw
    h = h * dh

    return x, y, w, h

6. 读取 XML 文件并转换为 TXT 文件

读取 XML 文件,提取目标信息,将其转换为 YOLO 格式,并写入 TXT 文件。

复制代码
def readxml(i):
    f_dir = input_dir + "\\" + i + ".xml"
    txtresult = ''

    outfile = open(f_dir, encoding='UTF-8')
    filetree = ET.parse(outfile)
    outfile.close()
    root = filetree.getroot()

    size = root.find('size')
    width = int(size.find('width').text)
    height = int(size.find('height').text)
    imgshape = (width, height)

    for obj in root.findall('object'):
        obj_name = obj.find('name').text
        obj_id = class_list.index(obj_name)
        bbox = obj.find('bndbox')
        xmin = float(bbox.find('xmin').text)
        xmax = float(bbox.find('xmax').text)
        ymin = float(bbox.find('ymin').text)
        ymax = float(bbox.find('ymax').text)
        bbox_coor = (xmin, xmax, ymin, ymax)

        x, y, w, h = ConverCoordinate(imgshape, bbox_coor)
        txt = '{} {} {} {} {}\n'.format(obj_id, x, y, w, h)
        txtresult += txt

    with open(out_dir + "\\" + i + ".txt", 'w+') as f:
        f.write(txtresult)

7. 主函数

  • 获取 XML 文件列表。

  • 提取所有分类并打印。

  • 逐个将 XML 文件转换为 YOLO 格式的 TXT 文件。

  • 生成一个 classes.txt 文件,列出所有类别。

    filelist = file_name(input_dir)
    get_class(filelist)
    print(class_list)

    for i in filelist:
    readxml(i)

    with open(out_dir + "\classes.txt", 'a') as f:
    classresult = '\n'.join(class_list) + '\n'
    f.write(classresult)

完整程序

该脚本用于将 XML 文件中的对象标注转换为 YOLO 格式的 TXT 文件,并生成一个包含所有类别的 classes.txt 文件。通过这些步骤,可以方便地将标注数据用于 YOLO 模型的训练。

复制代码
import os
import xml.etree.ElementTree as ET

# xml文件存放目录(不要以\结尾)
input_dir = r'D:/lenovo/Archie/shujukuochongv1.0/xmlall1'

# 输出txt文件目录(不要以\结尾)
out_dir = r'D:/lenovo/Archie/shujukuochongv1.0/txtall1'
#类别名
class_list = ['1','2','3','4','5','6','7','8','9']


# 获取目录所有xml文件
def file_name(input_dir):
    F = []
    for root, dirs, files in os.walk(input_dir):

        for file in files:
            # print file.decode('gbk')    #文件名中有中文字符时转码
            if os.path.splitext(file)[1] == '.xml':
                t = os.path.splitext(file)[0]
                F.append(t)  # 将所有的文件名添加到L列表中
    return F  # 返回L列表


# 获取所有分类
def get_class(filelist):
    for i in filelist:
        f_dir = input_dir + "\\" + i + ".xml"
        in_file = open(f_dir, encoding='UTF-8')
        filetree = ET.parse(in_file)
        in_file.close()
        root = filetree.getroot()
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            cls = obj.find('name').text
            if cls not in class_list or int(difficult) == 1:
                class_list.append(cls)


def ConverCoordinate(imgshape, bbox):
    # 将xml像素坐标转换为txt归一化后的坐标
    xmin, xmax, ymin, ymax = bbox
    width = imgshape[0]
    height = imgshape[1]
    dw = 1. / width
    dh = 1. / height
    x = (xmin + xmax) / 2.0
    y = (ymin + ymax) / 2.0
    w = xmax - xmin
    h = ymax - ymin

    # 归一化
    x = x * dw
    y = y * dh
    w = w * dw
    h = h * dh

    return x, y, w, h


def readxml(i):
    f_dir = input_dir + "\\" + i + ".xml"

    txtresult = ''

    outfile = open(f_dir, encoding='UTF-8')
    filetree = ET.parse(outfile)
    outfile.close()
    root = filetree.getroot()

    # 获取图片大小
    size = root.find('size')
    width = int(size.find('width').text)
    height = int(size.find('height').text)
    imgshape = (width, height)

    # 转化为yolov的格式
    for obj in root.findall('object'):
        # 获取类别名
        obj_name = obj.find('name').text

        obj_id = class_list.index(obj_name)
        # 获取每个obj的bbox框的左上和右下坐标
        bbox = obj.find('bndbox')
        xmin = float(bbox.find('xmin').text)
        xmax = float(bbox.find('xmax').text)
        ymin = float(bbox.find('ymin').text)
        ymax = float(bbox.find('ymax').text)
        bbox_coor = (xmin, xmax, ymin, ymax)

        x, y, w, h = ConverCoordinate(imgshape, bbox_coor)
        txt = '{} {} {} {} {}\n'.format(obj_id, x, y, w, h)
        txtresult = txtresult + txt

    # print(txtresult)
    f = open(out_dir + "\\" + i + ".txt", 'w+')
    f.write(txtresult)
    f.close()


# 获取文件夹下的所有文件
filelist = file_name(input_dir)

# 获取所有分类
get_class(filelist)

# 打印class
print(class_list)

# xml转txt
for i in filelist:
    readxml(i)

# 在out_dir下生成一个class文件
f = open(out_dir + "\\classes.txt", 'a')
classresult = ''
for i in class_list:
    classresult = classresult + i + "\n"
f.write(classresult)
f.close()
相关推荐
liuhaoran___1 小时前
计算机求职面试中高频出现的经典题目分类整理
python
AI绘画月月1 小时前
AI绘画 | Stable Diffusion 图片背景完美替换
图像处理·人工智能·计算机视觉·ai作画·stable diffusion·midjourney·sd
不辉放弃2 小时前
零基础讲解pandas
开发语言·python
databook2 小时前
线性判别分析(LDA):降维与分类的完美结合
python·机器学习·scikit-learn
慕丹2 小时前
虫洞数观系列三 | 数据分析全链路实践:Pandas清洗统计 + Navicat可视化呈现
python·mysql·数据挖掘·数据分析·pandas
ZHW_AI课题组2 小时前
调用阿里云API实现运营商实名认证
python·阿里云·云计算·api
闲人编程2 小时前
图像插值算法(最近邻/双线性/立方卷积)
python·opencv·图像识别
创新技术阁3 小时前
FastAPI 的两大核心组件:Starlette 和 Pydantic 详解
后端·python
关山月3 小时前
被低估的服务器发送事件(SSE)
python
DeepLink3 小时前
Python小练习系列:学生信息排序(sorted + key函数)
python·求职