1、修改class_names添加自己的类名
2、设置vocPath,即xml数据文件夹的主目录。
3、设置主目录下的xml文件名(vocPath)和txt文件名(txtPath)。
# 导入必要的库
import os.path
import xml.etree.ElementTree as ET
# 定义类别名称
class_names = ["cat", "dog"]
# 定义VOC数据集的路径
vocPath = r'path/Main'
# 定义XML文件路径和转换后的TXT文件存放路径
xmlPath = vocPath + r'\labels_voc'
txtPath = vocPath + r'\labels_txt'
# 如果输出目录不存在,则创建
if not os.path.exists(txtPath):
os.makedirs(txtPath)
# 初始化存储文件名的列表
files = []
# 遍历XML文件目录
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 = os.path.join(xmlPath, xml_name)
txt_file_name = os.path.join(txtPath, txt_name)
# 打开XML文件并解析
xml_file = open(xml_file_name, encoding='gb18030', errors='ignore')
tree = ET.parse(xml_file)
root = tree.getroot()
# 获取图像宽度和高度
w = int(root.find('size').find('width').text)
h = int(root.find('size').find('height').text)
# 打开TXT文件以写入转换后的坐标信息
f_txt = open(txt_file_name, 'w+')
content = ""
first = True
# 遍历XML文件中的目标对象
for obj in root.iter('object'):
# 获取目标类别名称
name = obj.find('name').text
# 若只有一类 ,即 class_num = 0
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)
# 根据VOC格式,计算归一化坐标并构建每个目标的行信息
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(content)
# 将内容写入TXT文件
f_txt.write(content)
# 关闭文件
f_txt.close()
xml_file.close()
i += 1