YOLOv5、YOLOv7—xml转txt,txt转xml(亲测可用)

在使用YOLOv5和YOLOv7训练时,经常需要对数据集的标注文件进行格式转换,因此将txt转xml,xml转txt的代码记录下来,便于使用。

图片来源于下文中的第一个博客链接

xml转txt的代码
import glob
import os
# xml文件的路径
xml_path = 'E:/dataset/datas/VOC2007/Annotations/'

#定义从xml获取信息的函数
def _read_anno(filename):

    import xml.etree.ElementTree as ET
    tree = ET.parse(filename)
    #获取宽w和高h
    a = tree.find('size')
    w,h = [int(a.find('width').text),
           int(a.find('height').text)]
    print(w,h)

    objects = []
    #这里是针对错误xml文件,图片的w和h都为0,这样的xml文件可以直接忽视,返回空列表
    if w == 0:
        return []
    #这里需要根据需要修改,因为我训练的目的是判断是否戴了头盔,因此从xml获取的name为none或者0的label都为0,其他的颜色或者1都为1
    for obj in tree.findall('object'):
    	#获取name,我上边的实例图片中的红色区域
        name = obj.find('name').text
        #修改label,这里是不同数据集大融合的关键
        if name == 'person':
            label = 0
        else:
            label = 1
		#读取检测框的左上、右下角点的坐标
        bbox = obj.find('bndbox')
        x1, y1, x2, y2 = [int(bbox.find('xmin').text),
                          int(bbox.find('ymin').text),
                          int(bbox.find('xmax').text),
                          int(bbox.find('ymax').text)]
		#这里也很关键,yolov5需要中心点以及宽和高的标注信息,并且进行归一化,下边label后边的四个值即是归一化后保留4位有效数字的x,y,w,h
        obj_struct = [label,round((x1+x2)/(2.0*w),4), round((y1+y2)/(2.0*h),4), round((x2-x1)/(w),4),round((y2-y1)/(h),4)]
        print(obj_struct)

        objects.append(obj_struct)


    return objects
#接下来是写入txt文件中
if __name__ == '__main__':
    #定义一个空的字符串
    t = ''
    # txt文件存放的路径
    txt_path = "E:/dataset/datas/VOC2007/labels/"
    #获取所有的xml文件路径
    allfilepath = []
    for file in os.listdir(xml_path):
        if file.endswith('.xml'):
            file = os.path.join(xml_path,file)
            allfilepath.append(file)
            # print(allfilepath)
        else:
            pass
     #生成需要的对应xml文件名的txt
    for file in allfilepath:
        print("file", file)
        #获取xml的文件名
        filename = file.split('/')[5]
        indexname = filename.split('.')[0]
        # print('indexname', indexname)
        result = _read_anno(file)
        # print('result', result)
        #跳过空列表
        if len(result)==0:
            continue
        #写入信息,注意每次循环结束都把t重新定义,result是一个二维列表(行数为目标个数,列对应label和位置信息),为了避免读取出错(还有一个原因是我菜),我们一个一个的写入。       
        txtfile = open(os.path.join(txt_path,indexname+'.txt'), 'w')
        for line in result:
            for a in line:
                # print('a', a)
                t = t + str(a) + ' '
                # print('t', t)
                txtfile.writelines(t)
                t = ''
            txtfile.writelines('\n')            

xml转txt的代码是很早之前用的,当时参考一个博主的代码进行了修改,但是现在找不到那篇博主的文章了,侵权请联系删除。

txt转xml的代码
# .txt-->.xml
# ! /usr/bin/python
# -*- coding:UTF-8 -*-
import os
import cv2
 
def txt_to_xml(txt_path, img_path, xml_path):
    # 1.字典对标签中的类别进行转换
    dict = {
            '0': "person",
           }
    # 2.找到txt标签文件夹
    files = os.listdir(txt_path)
    # 用于存储 "老图"
    pre_img_name = ''
    # 3.遍历文件夹
    for i, name in enumerate(files):
        # 许多人文件夹里有该文件,默认的也删不掉,那就直接pass
        if name == "desktop.ini":
            continue
        print(name)
        # 4.打开txt
        txtFile = open(txt_path + name)
        # 读取所有内容
        txtList = txtFile.readlines()
        # 读取图片名称
        img_name = name[:-4]
        pic = cv2.imread(img_path + img_name + ".jpg")
        # 获取图像大小信息
        Pheight, Pwidth, Pdepth = pic.shape
        # 5.遍历txt文件中每行内容
        for row in txtList:
            # 按' '分割txt的一行的内容
            oneline = row.strip().split(" ")
            # 遇到的是一张新图片
            if img_name != pre_img_name:
                # 6.新建xml文件
                xml_file = open((xml_path + img_name + '.xml'), 'w')
                xml_file.write('<annotation>\n')
                xml_file.write('    <folder>VOC2007</folder>\n')
                xml_file.write('    <filename>' + img_name + '.jpg' + '</filename>\n')
                xml_file.write('<source>\n')
                xml_file.write('<database>orgaquant</database>\n')
                xml_file.write('<annotation>organoids</annotation>\n')
                xml_file.write('</source>\n')
                xml_file.write('    <size>\n')
                xml_file.write('        <width>' + str(Pwidth) + '</width>\n')
                xml_file.write('        <height>' + str(Pheight) + '</height>\n')
                xml_file.write('        <depth>' + str(Pdepth) + '</depth>\n')
                xml_file.write('    </size>\n')
                xml_file.write('            <segmented>0</segmented>\n')
                xml_file.write('    <object>\n')
                xml_file.write('<name>' + dict[oneline[0]] + '</name>\n')
                xml_file.write('                    <pose>Unspecified</pose>\n')
                xml_file.write('                    <truncated>0</truncated>\n')
                xml_file.write('                    <difficult>0</difficult>\n')
                xml_file.write('        <bndbox>\n')
                xml_file.write('            <xmin>' + str(
                    int(((float(oneline[1])) * Pwidth) - (float(oneline[3])) * 0.5 * Pwidth)) + '</xmin>\n')
                xml_file.write('            <ymin>' + str(
                    int(((float(oneline[2])) * Pheight) - (float(oneline[4])) * 0.5 * Pheight)) + '</ymin>\n')
                xml_file.write('            <xmax>' + str(
                    int(((float(oneline[1])) * Pwidth) + (float(oneline[3])) * 0.5 * Pwidth)) + '</xmax>\n')
                xml_file.write('            <ymax>' + str(
                    int(((float(oneline[2])) * Pheight) + (float(oneline[4])) * 0.5 * Pheight)) + '</ymax>\n')
                xml_file.write('        </bndbox>\n')
                xml_file.write('    </object>\n')
                xml_file.close()
                pre_img_name = img_name  # 将其设为"老"图
            else:  # 不是新图而是"老图"
                # 7.同一张图片,只需要追加写入object
                xml_file = open((xml_path + img_name + '.xml'), 'a')
                xml_file.write('    <object>\n')
                xml_file.write('<name>' + dict[oneline[0]] + '</name>\n')
                '''  按需添加这里和上面
                xml_file.write('        <pose>Unspecified</pose>\n')
                xml_file.write('        <truncated>0</truncated>\n')
                xml_file.write('        <difficult>0</difficult>\n')
                '''
                xml_file.write('        <bndbox>\n')
                xml_file.write('            <xmin>' + str(
                    int(((float(oneline[1])) * Pwidth) - (float(oneline[3])) * 0.5 * Pwidth)) + '</xmin>\n')
                xml_file.write('            <ymin>' + str(
                    int(((float(oneline[2])) * Pheight) - (float(oneline[4])) * 0.5 * Pheight)) + '</ymin>\n')
                xml_file.write('            <xmax>' + str(
                    int(((float(oneline[1])) * Pwidth) + (float(oneline[3])) * 0.5 * Pwidth)) + '</xmax>\n')
                xml_file.write('            <ymax>' + str(
                    int(((float(oneline[2])) * Pheight) + (float(oneline[4])) * 0.5 * Pheight)) + '</ymax>\n')
                xml_file.write('        </bndbox>\n')
                xml_file.write('    </object>\n')
                xml_file.close()
 
        # 8.读完txt文件最后写入</annotation>
        xml_file1 = open((xml_path + pre_img_name + '.xml'), 'a')
        xml_file1.write('</annotation>')
        xml_file1.close()
    print("Done !")
 
 
# 修改成自己的文件夹 注意文件夹最后要加上/
txt_to_xml("E:/dataset/datas/train/labels/", "E:/dataset/datas/train/images/", "E:/dataset/datas/train/Annotations/")

参考博客:https://blog.csdn.net/qq_42198461/article/details/126146431
https://blog.csdn.net/qq_58355216/article/details/128491575
感谢博主的分享。

  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要将XML格式换为YOLOv5所需的TXT格式,可以使用以下代码进行处理: ```python import os import xml.etree.ElementTree as ET def convert_xml_to_txt(xml_path, txt_path): # 打开XML文件 tree = ET.parse(xml_path) root = tree.getroot() with open(txt_path, 'w') as txt_file: for obj in root.findall('object'): # 获取对象的类别和边界框坐标 name = obj.find('name').text xmin = int(obj.find('bndbox/xmin').text) ymin = int(obj.find('bndbox/ymin').text) xmax = int(obj.find('bndbox/xmax').text) ymax = int(obj.find('bndbox/ymax').text) # 计算中心点坐标和边界框宽高 x_center = (xmin + xmax) / 2 y_center = (ymin + ymax) / 2 width = xmax - xmin height = ymax - ymin # 将数据写入TXT文件 line = f"{name} {x_center} {y_center} {width} {height}" txt_file.write(line + '\n') print(f"Successfully converted {xml_path} to {txt_path}") # 指定XML文件和输出TXT文件的路径 xml_file = 'path/to/input.xml' txt_file = 'path/to/output.txt' # XMLTXT convert_xml_to_txt(xml_file, txt_file) ``` 请将`path/to/input.xml`替换为输入XML文件的路径,将`path/to/output.txt`替换为输出TXT文件的路径。运行该代码后,将会生成对应的TXT文件,其中包含了每个对象的类别和边界框信息,符合YOLOv5的要求。 请注意,此代码仅适用于单个XML文件换。如果需要批量换,请使用适当的循环来处理多个文件。 中提供的XML示例中包含了一个对象的类别和边界框信息。你可以根据自己的XML文件结构进行相应的调整以匹配代码中的解析逻辑。 希望以上信息对你有所帮助!如果有任何进一步的问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值