天天看點

資料格式轉換格式介紹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

然後打開軟體,測試是否轉換成功。

繼續閱讀