最近学习图像识别在训练模型时需要将不同模型需要的标注格式来回批量转换,本文介绍了2种方法可以将XML和TXT标注信息相互转换。
网上看了很别人的例子但是发现很多都会在顶部出现,’。
尝试了很多方法后发现https://blog.csdn.net/donkey_1993/article/details/96327270和https://blog.csdn.net/weixin_43202256/article/details/83185089的思路很有效,就是通过一个已存在的标准格式的XML文件将其他的在这上面做修改后输出成新的XML文件。这种方法就不会存在注释且简单代码量少。
————————————————
版权声明:本文为CSDN博主「和美琪一起的日子里」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43202256/article/details/83185089 | |
---|---|
首先介绍第一种TXT转成XML格式
我的txt文件的格式如下存储了图片信息的txt文件格式(filename x_min,y_min,x_max,y_max,label)
我做的是一个人和带帽子人的识别,0为没戴帽子的人,1为带帽子的人。
要批量转换的xml文件格式如下
from lxml.etree import Element, SubElement, tostring, ElementTree
import numpy as np
import cv2
import copy
def cv_imread(file_path):
cv_img=cv2.imdecode(np.fromfile(file_path,dtype=np.uint8),-1)#当图片的路径存在中文时,使用此函数读图就不会报错了
return cv_img
def TXTtoXML(train_file,folderphoto,savepathfinal):
with open(train_file) as f:
trainfiles = f.readlines()
tree = ElementTree()
for line in trainfiles:
trainFile = line.split()#将该行按空格切分
#print(trainFile,(len(trainFile)))
path = folderphoto+trainFile[0]
filename=trainFile[0]
print(filename)
print(type(filename))
photonum=filename[0:-4]
jpg_dirtory = path
img_name = jpg_dirtory.split('/')[-1]
print(path)
im = cv_imread(path)
w = im.shape[1] #img.shape[1]是图片的宽度
h = im.shape[0]#img.shape[0]是图片的高度
d = im.shape[2]#img.shape[0]是图片的深度
# print w,h,d
tree.parse(template_file)
root = tree.getroot()
root.find('filename').text = img_name
root.find('path').text = path
sz=root.find('size')
sz.find('height').text = str(w)
sz.find('width').text = str(h)
sz.find('depth').text = str(d)
print(path)
print(len(trainFile))#检测到人的个数减一
for i in range(1,len(trainFile),1):
detail= trainFile[i].split(',')
#print(type(detial))
xmin = str(int(float(detail[0])))
ymin = str(int(float(detail[1])))
xmax = str(int(float(detail[2])))
ymax = str(int(float(detail[3])))
label = detail[4]#类型我这里用0表示person,1表示带hat带帽子的人
print(xmin, ymin, xmax, ymax, label) # 判断有多少个空格分隔的,第0个是文件名,第1个是第一个目标的信息,第二个是第二个目标的信息。将其用‘,’分割
if i==1:#因为我这是多目标检测所以需要加个判断,当只有一个框的时候替换原来的模板上的object
obj = root.find('object')
obj.find('name').text = label.replace('0', 'person').replace('1','hat')
bb = obj.find('bndbox')
bb.find('xmin').text = xmin
bb.find('ymin').text = ymin
bb.find('xmax').text = xmax
bb.find('ymax').text = ymax
else:#当写入第二个以上框的数据时添加ojbect
root = tree.getroot()
obj_ori = root.find('object')
obj = copy.deepcopy(obj_ori) # 注意这里深拷贝
obj.find('name').text = label.replace('0', 'person').replace('1','hat')
bb = obj.find('bndbox')
bb.find('xmin').text = xmin
bb.find('ymin').text = ymin
bb.find('xmax').text = xmax
bb.find('ymax').text = ymax
root.append(obj)
savepath=savepathfinal+photonum+'.xml'
tree.write(savepath, encoding='utf-8')
if __name__ == "__main__":
template_file = 'E:/000000.xml'#XML实例
train_file = 'C:/Users/YXY/Desktop/TXTNEW/yidabiao.txt' # 存储了图片信息的txt文件格式(filename x_min,y_min,x_max,y_max,label)
folderphoto='C:/Users/YXY/Desktop/python脚本工具/photo/'#原始图片的路径
savepathfinal=r'E:/testxml/'#生成的xml文件存储路径
TXTtoXML(train_file,folderphoto,savepathfinal)
接下来介绍将XML转换成txt的代码,转换后的格式就跟最上面的txt内的内容一样。
import os
import os.path
import xml.etree.ElementTree as ET
import glob
def xml_to_txt(xmlpath,txtpath):
os.chdir(xmlpath)
annotations = os.listdir('.')
annotations = glob.glob(str(annotations)+'*.xml')
file_save = '/'+'train' + '.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,encoding='gb18030', errors='ignore')#可能是文本中会出现的一些特殊符号超出了gbk的编码范围,可以选择编码范围更广的‘gb18030’
tree=ET.parse(in_file)
root = tree.getroot()
L= ''
filename = root.find('filename').text
for obj in root.iter('object'):
name = obj.find('name').text
class_num = class_names.index(name)
xmlbox = obj.find('bndbox')
x1 = xmlbox.find('xmin').text
x2 = xmlbox.find('xmax').text
y1 = xmlbox.find('ymin').text
y2 = xmlbox.find('ymax').text
L+=x1+','+y1+','+x2+','+y2+','+str(class_num)+' '
f_w.write(filename+' '+L+'\n')
if __name__ == "__main__":
class_names = ['person','hat']#看你自己时用的哪些字符对分类进行命名对应修改。
xmlpath='E:/testxml'
txtpath='E:/testtxt'
xml_to_txt(xmlpath,txtpath)
————————————————