天天看点

数据格式转换格式介绍txt转xmlxml转txt

labelImg标注yolo的txt格式与xml格式之间的相互转换

  • 格式介绍
    • txt格式
    • xml格式
  • txt转xml
    • 准备
      • 第一步
      • 第二步
    • 生成list.txt
    • 生成xml格式
      • 第一步
      • 第二步
    • 验证
  • xml转txt
    • 转换
    • 验证

格式介绍

txt格式

数据格式转换格式介绍txt转xmlxml转txt

xml格式

数据格式转换格式介绍txt转xmlxml转txt

txt转xml

准备

第一步

首先建立一个文件夹,如new

在新建立的文件夹下建立两个文件夹:image,txt。同时将labeling.exe移入,方便之后验证。建立完如下:

数据格式转换格式介绍txt转xmlxml转txt

附:注意打开labeling.exe不能有中文路径,因此,自己新建的文件夹(new)也不能有中文路径。

第二步

将自己的图片放入image文件夹下

将要转换的txt文件放入txt文件夹下

准备工作完成。

生成list.txt

首先生成含有图片的位置的list.txt,代码如下

import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
    source_folder='C:\\Users\\Z6000\\Desktop\\new\\image'    #地址是所有图片的保存地点
    dest='C:\\Users\\Z6000\\Desktop\\new\\list.txt'          #保存list.txt的地址
    file_list=os.listdir(source_folder)                      #赋值图片所在文件夹的文件列表
    train_file=open(dest,'a')                                #打开文件
    num=1
    for file_obj in file_list:                               #访问文件列表中的每一个文件
        file_path=os.path.join(source_folder,file_obj) 
        #file_path保存每一个文件的完整路径
        file_name,file_extend=os.path.splitext(file_obj)
        #file_name 保存文件的名字,file_extend保存文件扩展名
        file_num=num
        #file_num=int(file_name)  
        if(file_num<620):                                   #这个数字620要大于你自己的数据
            train_file.write(file_path+'\n')  
        num=num+1
    train_file.close()#关闭文件
           

完成之后,生成的.txt文件内容如下:

数据格式转换格式介绍txt转xmlxml转txt

生成xml格式

此时文件夹如下

数据格式转换格式介绍txt转xmlxml转txt

第一步

将txt文件夹下的txt文件复制到image文件夹下,此时image文件夹下含有所有图片的.jpg和.txt

第二步

生成xml格式的文件

import cv2
import os
xml_head = '''<annotation>
    <folder>image</folder>                  #这个是你放图片的文件名,如果之前放图片的文件名不是这个要更改
    <filename>{}</filename>
    <path>{}</path>
    <source>
        <database>Unknown</database>
    </source>  
    <size>
        <width>{}</width>
        <height>{}</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    '''
xml_obj = '''
    <object>        
        <name>{}</name>
        <pose>Rear</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>{}</xmin>
            <ymin>{}</ymin>
            <xmax>{}</xmax>
            <ymax>{}</ymax>
        </bndbox>
    </object>
    '''
xml_end = '''
</annotation>'''
 
labels = ['A','B']                                                              #这个是你的标签名字,要修改
cnt = 0
with open('C:\\Users\\Z6000\\Desktop\\new\\list.txt','r') as train_list:        #这个是生成的list.txt的路径,要修改
    for lst in train_list.readlines():
        lst = lst.strip()
        jpg = lst                                                               #这个是图片的路径
        jpg_Str = str(jpg)
        jpg_Sp = jpg_Str.split("\\")
        jpg_name = jpg_Sp[-1]                                                   #这个是得到图片的名称
        txt = lst.replace('.jpg','.txt')                                        #这个是得到txt路径,因为之前有一步是将txt文件放到image中,因此此刻只要将.jpg替换为.txt就能得到路径   
        xml_path =jpg.replace('.jpg','.xml')                                    #这个是xml路径,在image文件夹下得到xml
 
        obj = ''
 
        img = cv2.imread(jpg)
        img_h,img_w = img.shape[0],img.shape[1]
        head = xml_head.format(str(jpg_name),str(jpg),str(img_w),str(img_h))
        with open(txt,'r') as f:
            for line in f.readlines():
                yolo_datas = line.strip().split(' ')
                label = int(float(yolo_datas[0].strip()))
                center_x = round(float(str(yolo_datas[1]).strip()) * img_w)
                center_y = round(float(str(yolo_datas[2]).strip()) * img_h)
                bbox_width = round(float(str(yolo_datas[3]).strip()) * img_w)
                bbox_height = round(float(str(yolo_datas[4]).strip()) * img_h)
 
                xmin = str(int(center_x - bbox_width / 2 ))
                ymin = str(int(center_y - bbox_height / 2))
                xmax = str(int(center_x + bbox_width / 2))
                ymax = str(int(center_y + bbox_height / 2))
 
                obj += xml_obj.format(labels[label],xmin,ymin,xmax,ymax)
        with open(xml_path,'w') as f_xml:
            f_xml.write(head+obj+xml_end)
        cnt += 1
        print(cnt)
           

注意:运行的时候要把上面代码的#注释删掉

运行之后在image文件夹下得到.xml文件

验证

打开labeling.exe

选择open dir,打开图片所在的文件夹image,即可看到标注结果

xml转txt

转换

在new文件夹下,有如下几个文件夹

数据格式转换格式介绍txt转xmlxml转txt

image中放的是图片

out中放的是xml文件

txt中放的是生成的txt的一个列表

最终生成的txt文件同xml在一个文件夹下即out下。

转换代码如下:

"""在自己定义的txtpath生成一个txt列表
   在与xml相同的文件夹下生成txt文件"""
import os
import os.path
import xml.etree.ElementTree as ET
import glob

class_names = ['outfire']                             #类别,要改
xmlpath='C:\\Users\\Z6000\\Desktop\\new\\out\\'       #xml的路径,要改
txtpath='C:\\Users\\Z6000\\Desktop\\new\\txt\\'       #txt的路径,一个txt列表,要改


def xml_to_txt(xmlpath,txtpath):

    os.chdir(xmlpath)
    annotations = os.listdir('.')
    annotations = glob.glob(str(annotations)+'*.xml')

    file_save = 'list' + '.txt'                     #在txt路径下生成一个列表,命名为list.txt,可改可不改
    file_txt = os.path.join(txtpath, file_save)
    f_w = open(file_txt, 'w')

    for i,file in enumerate(annotations):

        in_file = open(file)
        current_file_path=os.path.dirname(os.path.abspath(file))  #获取当前文件所在的路径
        txt_name=file.replace('.xml','.txt')                      #最终文件名字 
        txt_path=current_file_path+'\\'+txt_name                  #最终文件路径

        tree=ET.parse(in_file)              # 直接解析xml文件
        root = tree.getroot()               # 获取xml文件的根节点


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

        for obj in root.iter('object'):
                current = list()
                name = obj.find('name').text

                class_num = class_names.index(name)

                xmlbox = obj.find('bndbox')

                x1 = float(xmlbox.find('xmin').text)
                x2 = float(xmlbox.find('xmax').text)
                y1 = float(xmlbox.find('ymin').text)
                y2 = float(xmlbox.find('ymax').text)
                
         
                
                dw = 1./w
                dh = 1./h
                xx = (x1 + x2)/2.0
                yy = (y1 + y2)/2.0
                ww = x2 - x1
                hh = y2 - y1
                xx = xx*dw
                ww = ww*dw
                yy = yy*dh
                hh = hh*dh
                xx=round(xx,6)
                ww=round(ww,6)
                yy=round(yy,6)
                hh=round(hh,6)
                xxx = str(xx)
                www = str(ww)
                yyy = str(yy)
                hhh = str(hh)

                f_w.write(filename+'.jpg '+xxx+','+yyy+','+www+','+hhh+','+str(class_num)+'\n')
                with open(txt_path,'a') as f_xml:
                      f_xml.write(str(class_num)+' '+xxx+' '+yyy+' '+www+' '+hhh+'\n')

xml_to_txt(xmlpath,txtpath)
           

最终生成文件如下:

数据格式转换格式介绍txt转xmlxml转txt
数据格式转换格式介绍txt转xmlxml转txt

验证

验证时,把out文件夹下面的xml文件删除,同时添加类别文件class.txt

如下:

数据格式转换格式介绍txt转xmlxml转txt

然后打开软件,测试是否转换成功。

继续阅读