python文件操作之xml转txt

在使用yolo进行深度学习训练时,我们所使用的标签文件都是txt格式的,但是有的人使用的标注软件生成的可能是xml文件,那么就需要使用python工具写一个格式转换脚本。

首先导入库,并定义标注的图片地址、生成的标签文件xml地址、存储结果txt的地址。

复制代码
import cv2
import os
import math
import xml.dom.minidom

path_img = r'/home/pc/下载/qq_file/test/img/'
path_xml = r'/home/pc/下载/qq_file/test/xml/'
path_txt = r'/home/pc/下载/qq_file/test/txt/'

files = os.listdir(path_xml)这句话的files存储了path_xml路径下的所有xml文件

复制代码
if __name__ == "__main__":
    files = os.listdir(path_xml)
    print("文件数量: " + str(len(files)))
    for file in files:
        print(file)

如上代码的file打印结果就应该为目标文件夹下所有xml文件的文件名,如246.xml。

复制代码
if __name__ == "__main__":
    files = os.listdir(path_xml)
    print("文件数量: " + str(len(files)))
    for file in files:
        print(file)
        xmlname = file.split('.')
        txtname = xmlname[0] + '.txt'
        imgname = xmlname[0] + '.jpg'

        txtpath = path_txt + txtname
        imgpath = path_img + imgname
        xmlpath = path_xml + xmlname[0] + '.' + xmlname[1]

接下来用" . "来分割xml文件的文件名和后缀,其中xmlname0 = 文件名,xmlname1 = xml。由此可以定义每一个xml、txt、jpg的路径。

复制代码
if __name__ == "__main__":
    files = os.listdir(path_xml)
    print("文件数量: " + str(len(files)))
    for file in files:
        print(file)
        xmlname = file.split('.')
        txtname = xmlname[0] + '.txt'
        imgname = xmlname[0] + '.jpg'

        txtpath = path_txt + txtname
        imgpath = path_img + imgname
        xmlpath = path_xml + xmlname[0] + '.' + xmlname[1]
        # print(xmlpath)

        file_txt = open(txtpath, 'w+')
        frame = cv2.imread(imgpath)
        pixel_size = frame.shape[0]
        print(pixel_size)

接下来定义file_txt为文件夹下每一个txt文件,并可进行write操作。

复制代码
# 将解析xml文件的结果存在dom变量下
        dom = xml.dom.minidom.parse(xmlpath)
        # 获取xml文件的根元素
        root = dom.documentElement
        objects = root.getElementsByTagName('object')

        for obj in objects:
            name = obj.getElementsByTagName('name')[0]  # [0]可能代表包含标签数值的一个集合(这里可能包含标签数值,地址等)
            if name.childNodes[0].data == 'armor_red':  # 通过调用name.childNodes[0].data方法获取标签数值
                file_txt.write('0 ')
            elif name.childNodes[0].data == 'full_red':
                file_txt.write('1 ')
            elif name.childNodes[0].data == 'R_red':
                file_txt.write('2 ')
            else:
                print(file + ":label error")

            robodbox = obj.getElementsByTagName('robodbox')
            cx = obj.getElementsByTagName('cx')[0]
            cy = obj.getElementsByTagName('cy')[0]
            w = obj.getElementsByTagName('w')[0]
            h = obj.getElementsByTagName('h')[0]
            angle = obj.getElementsByTagName('angle')[0]
            # print(f"cx = {cx.childNodes[0]}, cy = {cy.childNodes[0].data}, w = {w.childNodes[0].data}, h = {h.childNodes[0].data}, "
            #       f"angle = {angle.childNodes[0].data}")

            temp_cx = str(float(cx.childNodes[0].data) / pixel_size)
            temp_cy = str(float(cy.childNodes[0].data) / pixel_size)
            temp_h = str(float(h.childNodes[0].data) / pixel_size)
            temp_w = str(float(w.childNodes[0].data) / pixel_size)
            temp_angle = str(float(angle.childNodes[0].data) / math.pi*180)

接下来对xml文件进行解析,调用dom = xml.dom.minidom.parse(xmlpath),将解析xml文件的结果存在dom变量下;root = dom.documentElement,获取xml文件的根元素root;objects = root.getElementsByTagName('object'),获得object;使用for循环遍历每一个object,使用name = obj.getElementsByTagName('name')0来获得每一个object的name,这里0可能代表包含标签数值的一个集合(这里可能包含标签数值,地址等),然后判断

if name.childNodes0.data == 'armor_red'

file_txt.write('0 ')

通过调用name.childNodes0.data方法获取标签数值,写入txt文件作为第一个数值,即"类别"。

复制代码
            robodbox = obj.getElementsByTagName('robodbox')
            cx = obj.getElementsByTagName('cx')[0]
            cy = obj.getElementsByTagName('cy')[0]
            w = obj.getElementsByTagName('w')[0]
            h = obj.getElementsByTagName('h')[0]
            angle = obj.getElementsByTagName('angle')[0]
            # print(f"cx = {cx.childNodes[0]}, cy = {cy.childNodes[0].data}, w = {w.childNodes[0].data}, h = {h.childNodes[0].data}, "
            #       f"angle = {angle.childNodes[0].data}")

            temp_cx = str(float(cx.childNodes[0].data) / pixel_size)
            temp_cy = str(float(cy.childNodes[0].data) / pixel_size)
            temp_h = str(float(h.childNodes[0].data) / pixel_size)
            temp_w = str(float(w.childNodes[0].data) / pixel_size)
            temp_angle = str(float(angle.childNodes[0].data) / math.pi*180)

            file_txt.write(temp_cx + ' ')
            file_txt.write(temp_cy + ' ')
            file_txt.write(temp_w + ' ')
            file_txt.write(temp_h + ' ')
            file_txt.write(temp_angle + ' ')
            file_txt.write('\n')

类别信息获取后,接下来对矩形框数值进行解析,使用同样的方法获取数据,并进行归一化写入txt。

完整代码如下

复制代码
import cv2
import os
import math
import xml.dom.minidom

path_img = r'/home/pc/下载/qq_file/test/img/'
path_xml = r'/home/pc/下载/qq_file/test/xml/'
path_txt = r'/home/pc/下载/qq_file/test/txt/'

if __name__ == "__main__":
    files = os.listdir(path_xml)
    print("文件数量: " + str(len(files)))
    for file in files:
        print(file)
        xmlname = file.split('.')
        txtname = xmlname[0] + '.txt'
        imgname = xmlname[0] + '.jpg'

        txtpath = path_txt + txtname
        imgpath = path_img + imgname
        xmlpath = path_xml + xmlname[0] + '.' + xmlname[1]
        # print(xmlpath)

        file_txt = open(txtpath, 'w+')
        frame = cv2.imread(imgpath)
        pixel_size = frame.shape[0]
        # print(pixel_size)

        # 将解析xml文件的结果存在dom变量下
        dom = xml.dom.minidom.parse(xmlpath)
        # 获取xml文件的根元素
        root = dom.documentElement
        objects = root.getElementsByTagName('object')

        for obj in objects:
            name = obj.getElementsByTagName('name')[0]  # [0]可能代表包含标签数值的一个集合(这里可能包含标签数值,地址等)
            if name.childNodes[0].data == 'armor_red':  # 通过调用name.childNodes[0].data方法获取标签数值
                file_txt.write('0 ')
            elif name.childNodes[0].data == 'full_red':
                file_txt.write('1 ')
            elif name.childNodes[0].data == 'R_red':
                file_txt.write('2 ')
            else:
                print(file + ":label error")

            robodbox = obj.getElementsByTagName('robodbox')
            cx = obj.getElementsByTagName('cx')[0]
            cy = obj.getElementsByTagName('cy')[0]
            w = obj.getElementsByTagName('w')[0]
            h = obj.getElementsByTagName('h')[0]
            angle = obj.getElementsByTagName('angle')[0]
            # print(f"cx = {cx.childNodes[0]}, cy = {cy.childNodes[0].data}, w = {w.childNodes[0].data}, h = {h.childNodes[0].data}, "
            #       f"angle = {angle.childNodes[0].data}")

            temp_cx = str(float(cx.childNodes[0].data) / pixel_size)
            temp_cy = str(float(cy.childNodes[0].data) / pixel_size)
            temp_h = str(float(h.childNodes[0].data) / pixel_size)
            temp_w = str(float(w.childNodes[0].data) / pixel_size)
            temp_angle = str(float(angle.childNodes[0].data) / math.pi*180)

            file_txt.write(temp_cx + ' ')
            file_txt.write(temp_cy + ' ')
            file_txt.write(temp_w + ' ')
            file_txt.write(temp_h + ' ')
            file_txt.write(temp_angle + ' ')
            file_txt.write('\n')

        print("ok")
        file_txt.close()
相关推荐
ebiobiz33 分钟前
极海 APM32 使用 Nimmake 编译指南
c++·python·单片机·嵌入式硬件·mcu
青山木35 分钟前
Hot 100 --- 编辑距离
java·数据结构·算法·leetcode·动态规划
朝朝辞暮i35 分钟前
C++ 第 26 课:对象、指针与 ->
java·开发语言·c++
长弓三石39 分钟前
把 AgentScope Harness 装进 RuoYi-Vue-Plus:纯 Java AI 平台的集成实践
java·人工智能·agent
蜗牛互联网41 分钟前
MongoDB Atlas Agent Engine之后,如何用版本门禁防止陈旧写入
java·数据库·人工智能·后端·mongodb
长弓三石42 分钟前
企业级智能体的权限到底怎么落地?以 BizBuddy 为例
java·人工智能·agent
慢云智慧空间42 分钟前
从智能终端到空间AI,慢云科技如何重新定义智慧建筑的核心能力?
人工智能·python·科技
用户4270276726811 小时前
一次缓存优化:SQL 从 502 降到 5
java
2601_962885721 小时前
如何用 Python 做股价历史分位选股?(筛出处于历史低位的股票)
开发语言·python
小师兄吃牛肉1 小时前
C语言指针进阶全解析
java·c语言·算法