txt 转 xml (亲测有效)

写在前面:

安排多人进行数据标注时需要注意3点,软件的版本(版本的兼容情况),软件的参数设置数据标注的规范

使用说明:

1.图像和标签文件(txt格式)放一起
注意:(因为使用cv2.imread读取图像,路径中不能有中文
特别注意: 路径有中文也会导致图片和xml文件匹配不上,labelimg上不显示框

在这里插入图片描述

2.图像文件名和 txt 文件名一样(后缀不要改)
3.最后生成的 xmltxt 和图像放在同一个文件里面

在这里插入图片描述

4.如果需要使用 labelimg 查看效果,建议把 xml 单独拿出来,并把标签路径指定到 xml 的保存路径

完整代码

import time
import os
from PIL import Image
import cv2
import numpy as np

'''人为构造xml文件的格式'''
out0 ='''<annotation>
    <folder>%(folder)s</folder>
    <filename>%(name)s</filename>
    <path>%(path)s</path>
    <source>
        <database>None</database>
    </source>
    <size>
        <width>%(width)d</width>
        <height>%(height)d</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
'''
out1 = '''    <object>
        <name>%(class)s</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>%(xmin)d</xmin>
            <ymin>%(ymin)d</ymin>
            <xmax>%(xmax)d</xmax>
            <ymax>%(ymax)d</ymax>
        </bndbox>
    </object>
'''

out2 = '''</annotation>
'''

'''txt转xml函数'''
def translate(fdir,lists): 
    source = {}
    label = {}
    for jpg in lists:
        print(jpg)
        if jpg[-4:] == '.jpg':
            image= cv2.imread(jpg)#路径不能有中文
            h,w,_ = image.shape #图片大小
#            cv2.imshow('1',image)
#            cv2.waitKey(1000)
#            cv2.destroyAllWindows()
            
            fxml = jpg.replace('.jpg','.xml')
            fxml = open(fxml, 'w');
            imgfile = jpg.split('/')[-1]
            source['name'] = imgfile 
            source['path'] = jpg
            source['folder'] = os.path.basename(fdir)

            source['width'] = w
            source['height'] = h
            
            fxml.write(out0 % source)
            txt = jpg.replace('.jpg','.txt')

            lines = np.loadtxt(txt)#读入txt存为数组
            #print(type(lines))

            for box in lines:
                #print(box.shape)
                if box.shape != (5,):
                    box = lines
                    
                '''把txt上的第一列(类别)转成xml上的类别
                   我这里是labelimg标1、2、3,对应txt上面的0、1、2'''
                label['class'] = str(int(box[0])+1) #类别索引从1开始
                
                '''把txt上的数字(归一化)转成xml上框的坐标'''
                xmin = float(box[1] - 0.5*box[3])*w
                ymin = float(box[2] - 0.5*box[4])*h
                xmax = float(xmin + box[3]*w)
                ymax = float(ymin + box[4]*h)
                
                label['xmin'] = xmin
                label['ymin'] = ymin
                label['xmax'] = xmax
                label['ymax'] = ymax

                # if label['xmin']>=w or label['ymin']>=h or label['xmax']>=w or label['ymax']>=h:
                #     continue
                # if label['xmin']<0 or label['ymin']<0 or label['xmax']<0 or label['ymax']<0:
                #     continue
                    
                fxml.write(out1 % label)
            fxml.write(out2)

if __name__ == '__main__':
    file_dir = 'G:/qing-litchi'#
    lists=[]
    for i in os.listdir(file_dir):
        if i[-3:]=='jpg':
            lists.append(file_dir+'/'+i)       
    #print(lists)
    translate(file_dir,lists)
    print('---------------Done!!!--------------')            
                

代码执行结果

在这里插入图片描述

公式理解

在这里插入图片描述

参考文章:Python把txt文件格式转换成VOC数据集的xml文件


版权声明:本文为weixin_42899627原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。