3种xml格式转yolo格式——正矩形框、斜矩形框

7 篇文章 0 订阅
3 篇文章 5 订阅

一、正矩形框

1、xml的第一种格式为:

<annotation>
	<source>
		<filename>1501.tif</filename>
		<origin>SAR</origin>
	</source>
	<research>
		<version>1.0</version>
		<author>team name</author>
		<pluginclass>Detection</pluginclass>
		<time>2021-07-2021-11</time>
	</research>
	<size>
		<width>1024</width>
		<height>1024</height>
	</size>
	<objects>
		<object>
			<coordinate>pixel</coordinate>
			<type>rectangle</type>
			<description>None</description>
			<possibleresult>
				<name>ARJ21</name>
				<probability>1</probability>
			</possibleresult>
			<points>
				<point>396.000000,719.000000</point>
				<point>447.000000,719.000000</point>
				<point>447.000000,765.000000</point>
				<point>396.000000,765.000000</point>
				<point>396.000000,719.000000</point>
			</points>
		</object>
	</objects>
</annotation>

对应的python代码如下:

import xml.etree.ElementTree as ET
import os

class_names = ['A220', 'A330', 'A320/321', 'Boeing737-800', 'Boeing787', 'ARJ21', 'other']
xmlpath = 'E:/plane/sar/xmllabels/'  # 原xml路径
txtpath = 'E:/plane/sar/txtlabels/'  # 转换后txt文件存放路径
if not os.path.exists(txtpath):
    os.makedirs(txtpath)
files = []

for root, dirs, files in os.walk(xmlpath):
    None

number = len(files)
print("文件数为", number)
i = 0
while i < number:

    name = files[i][0:-4]
    xml_name = name + ".xml"
    txt_name = name + ".txt"
    xml_file_name = xmlpath + xml_name
    txt_file_name = txtpath + txt_name

    xml_file = open(xml_file_name)
    tree = ET.parse(xml_file)
    root = tree.getroot()
    source = root.find("source")
    filename = source.find('filename').text

    # 图片名称
    image_name = source.find('filename').text

    w = int(root.find('size').find('width').text)
    h = int(root.find('size').find('height').text)

    f_txt = open(txt_file_name, 'w+')
    content = ""

    first = True

    for obj in root.find("objects").iter('object'):
        # 分类名称
        name = obj.find("possibleresult").find('name').text
        # 分类编号
        class_num = class_names.index(name)

        points = obj.find('points')

        # 获取第一个和第三个point元素的值
        first_point = points.findall('point')[0].text
        third_point = points.findall('point')[2].text

        # 将点的值解析为浮点数列表
        first_point_values = list(map(float, first_point.split(',')))
        third_point_values = list(map(float, third_point.split(',')))

        # 打印结果
        print(int(first_point_values[0]), first_point_values[1], third_point_values[0], third_point_values[1])

        # 左上角点x坐标
        x1 = int(first_point_values[0])
        # 右下角点x坐标
        x2 = int(third_point_values[0])
        # 左上角点y坐标
        y1 = int(first_point_values[1])
        # 右下角点y坐标
        y2 = int(third_point_values[1])

        if first:
            content += str(class_num) + " " + \
                       str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
                       str((x2 - x1) / w) + " " + str((y2 - y1) / h)
            first = False
        else:
            content += "\n" + \
                       str(class_num) + " " + \
                       str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
                       str((x2 - x1) / w) + " " + str((y2 - y1) / h)

    # print(str(i / (number - 1) * 100) + "%\n")
    print(content)
    f_txt.write(content)
    f_txt.close()
    xml_file.close()
    i += 1

print("done!")

2、xml的第二种格式为:

<annotation>
	<folder>PCB</folder>
	<filename>l_light_01_missing_hole_01_1_600</filename>
	<source>
		<database>My Database</database>
		<annotation>PCB</annotation>
		<image>flickr</image>
		<flickrid>NULL</flickrid>
	</source>
	<owner>
		<flickrid>NULL</flickrid>
		<name>idaneel</name>
	</owner>
	<size>
		<width>600</width>
		<height>600</height>
		<depth>3</depth>
	</size>
	<segmented>0</segmented>
	<object>
		<name>missing_hole</name>
		<pose>Unspecified</pose>
		<truncated>0</truncated>
		<difficult>0</difficult>
		<bndbox>
			<xmin>240</xmin>
			<ymin>404</ymin>
			<xmax>282</xmax>
			<ymax>437</ymax>
		</bndbox>
	</object>
</annotation>

对应的python代码为:

import os.path
import xml.etree.ElementTree as ET
import os
import random
# class_names = ['palm', 'stone', 'scissor', 'awesome', 'heartB', 'OK', 'ROCK', 'one', 'swear', 'thanks', 'heartA',
#                'heartC', 'good', 'bad', 'pray', 'call', 'take_picture', 'salute']
class_names = ['menopause', 'hairball', 'broken yarn', 'hole','stains']
xmlpath = 'F:/Project_code/yolov7-main/VOCdevkit/VOC2007/Annotations/'  # 原xml路径
txtpath = 'F:/Project_code/yolov7-main/VOCdevkit/VOC2007/labels_copy/'  # 转换后txt文件存放路径
if not os.path.exists(txtpath):
    os.makedirs(txtpath)
files = []

for root, dirs, files in os.walk(xmlpath):
    None

number = len(files)
print(number)
i = 0
while i < number:

    name = files[i][0:-4]
    xml_name = name + ".xml"
    txt_name = name + ".txt"
    xml_file_name = xmlpath + xml_name
    txt_file_name = txtpath + txt_name

    xml_file = open(xml_file_name)
    tree = ET.parse(xml_file)
    root = tree.getroot()
    filename = root.find('filename').text

    image_name = root.find('filename').text
    w = int(root.find('size').find('width').text)
    h = int(root.find('size').find('height').text)

    f_txt = open(txt_file_name, 'w+')
    content = ""

    first = True

    for obj in root.iter('object'):

        name = obj.find('name').text
        class_num = class_names.index(name)

        xmlbox = obj.find('bndbox')

        x1 = int(xmlbox.find('xmin').text)
        x2 = int(xmlbox.find('xmax').text)
        y1 = int(xmlbox.find('ymin').text)
        y2 = int(xmlbox.find('ymax').text)

        if first:
            content += str(class_num) + " " + \
                       str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
                       str((x2 - x1) / w) + " " + str((y2 - y1) / h)
            first = False
        else:
            content += "\n" + \
                       str(class_num) + " " + \
                       str((x1 + x2) / 2 / w) + " " + str((y1 + y2) / 2 / h) + " " + \
                       str((x2 - x1) / w) + " " + str((y2 - y1) / h)

    # print(str(i / (number - 1) * 100) + "%\n")
    print(content)
    f_txt.write(content)
    f_txt.close()
    xml_file.close()
    i += 1

print("done!")

二、斜矩形框

<object>
	<coordinate>pixel</coordinate>
	<type>rectangle</type>
	<description>None</description>
	<possibleresult>
		<name>A220</name>
	</possibleresult>
	<points>
		<point>316.000000,544.000000</point>
		<point>281.000000,575.000000</point>
		<point>250.000000,540.000000</point>
		<point>285.000000,509.000000</point>
		<point>316.000000,544.000000</point>
	</points>
</object>

1、先将xml格式转化为dota数据集格式

import os
import xml.etree.ElementTree as ET


# 定义一个函数来处理单个 XML 文件
def convert_xml_to_txt(xml_file, txt_file):
    # 解析 XML 文件
    tree = ET.parse(xml_file)
    root = tree.getroot()

    # 打开一个 txt 文件用于存储结果
    with open(txt_file, 'w') as f:
        # 遍历 XML 文件中的每个对象
        for obj in root.findall('.//object'):
            # 获取对象的名称
            name = obj.find('possibleresult/name').text
            # 获取对象的前四个点坐标,并将它们转换为整数
            points = obj.find('points')
            point_values = []
            for i in range(4):
                point = points.findall('point')[i].text.split(',')
                point_values.extend([int(float(p)) for p in point])
            # 将整数坐标值、名称和0写入 txt 文件
            f.write(f'{" ".join(map(str, point_values))} {name} 0\n')


# 定义要处理的文件夹路径和目标文件夹路径
source_folder_path = './xml_labels'  # 替换为你的源文件夹路径
target_folder_path = './txt_labels'  # 替换为你的目标文件夹路径

# 遍历源文件夹中的所有 XML 文件,并将每个文件转换为 TXT 文件保存到目标文件夹中
for filename in os.listdir(source_folder_path):
    if filename.endswith('.xml'):
        # 获取 XML 文件的完整路径
        xml_file = os.path.join(source_folder_path, filename)
        # 获取目标 TXT 文件的完整路径,并确保文件名一致
        txt_file = os.path.join(target_folder_path, filename.replace('.xml', '.txt'))
        # 调用函数将 XML 文件转换为 TXT 文件
        convert_xml_to_txt(xml_file, txt_file)

2、再通过以下文章中代码修改
全网首发!Yolov8_obb旋转框训练、测试、推理手把手教学(DOTA1.0数据集map50已达80%)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值