labelImg标注yolo的txt格式與xml格式之間的互相轉換
- 格式介紹
-
- txt格式
- xml格式
- txt轉xml
-
- 準備
-
- 第一步
- 第二步
- 生成list.txt
- 生成xml格式
-
- 第一步
- 第二步
- 驗證
- xml轉txt
-
- 轉換
- 驗證
格式介紹
txt格式
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuEzN4AzN1EjMxITNwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
xml格式
txt轉xml
準備
第一步
首先建立一個檔案夾,如new
在建立立的檔案夾下建立兩個檔案夾:image,txt。同時将labeling.exe移入,友善之後驗證。建立完如下:
附:注意打開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檔案内容如下:
生成xml格式
此時檔案夾如下
第一步
将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檔案夾下,有如下幾個檔案夾
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)
最終生成檔案如下:
驗證
驗證時,把out檔案夾下面的xml檔案删除,同時添加類别檔案class.txt
如下:
然後打開軟體,測試是否轉換成功。