labelImg标注yolo的txt格式与xml格式之间的相互转换
格式介绍
txt格式
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
如下:
然后打开软件,测试是否转换成功。