今天要做的是把两份不同的标注文件里面的标签进行合并。这工作在标注工作中是很有必要的。下面以把b文件夹中的标注文件上的标签转移到a文件夹中的标注文件上为例。说说我们编写的代码结构。
1、删除多余标签。
这个比较麻烦,要借助我们的标注工具上面的功能。最开始我写的代码是包含标签选择的,就是只选某个或者某几个标签来转移,但是标注过程中,你会发现不少标签做完标注的行数不一样,这样给我们在抽取标签的时候造成很大的麻烦,如下图:
所以后来我先把b文件夹中不需要抽取的标签删除掉了,再来进行b标签全部转移到a上面。
删除标签也就可以用下面的代码
import lxml.etree as ET
from tkinter import Tk
from tkinter import filedialog
import os
import glob
def parse_xml():
root = Tk()
root.withdraw()
#root_dir = filedialog.askdirectory()
root_dir = './cs/'
for root_path, dirs, files in os.walk(root_dir):
for name in files:
print(name)
if name.split('.')[-1] == 'xml':
print(root_path,name)
file_name = os.path.join(root_path,name)
print("文件名:",file_name,os.path.exists(file_name))
tree = ET.parse(file_name)
root = tree.getroot()
for node in root.iter('object'):
#print(child.tag,child.attrib,child.text) #二级节点标签、属性、内容
for i in node:
if i.tag == 'name' and i.text == '1':#删除1的标签
print('删除:%s的1标签' %file_name)
root.remove(node)
elif i.tag == 'name' and i.text == '123':#删除123的标签
print('删除:%s的123标签' %file_name)
root.remove(node)
print(file_name)
tree.write(file_name)
print('end')
if __name__ == '__main__':
parse_xml()
2、转移标签
import os
import shutil #这个是为了直接把b文件夹中有,a文件中没有的文件直接从b复制到a
dir1 = './a/' #a为待输入标签文件夹
dir2 = './b/' #b为待抽取标签文件夹
all_list1 = os.listdir(dir1) #a文件夹里面的东西生成列表
all_list2 = os.listdir(dir2) #b文件夹里面的东西生成列表
for x in range(len(all_list2)): #遍历b中每个文件为x
if all_list2[x] in all_list1: #如果x也在a中(同名)
xml1 = dir2 + all_list2[x] #xml1为x在b中的路径加x
xml2 = dir1 + all_list2[x] #xml2为x在a中的路径加x
f1 = open(xml1, 'r', encoding='UTF-8') #只读打开xml1(b文件夹)为f1
data1 = f1.readlines() #f1里面东西生成列表data1,用列表的形式,一行为一个列表,比如我们最后一行</annotation>就是这里面其中一个
f1.close() #关闭打开的xml1
f2 = open(xml2, 'r', encoding='UTF-8') #只读打开xml2(a文件夹)为f2
data2 = f2.read() #f2里面东西生成列表data2,用字符串的形式,如我们最后一行</annotation>,那么它读出来就是'<','/',a','n','n'.....'>'和'\n'而不是整行,这里\n是换行符一共14个
f2.close() #关闭打开的xml2
f3 = open(xml2, 'w', encoding='UTF-8') #读写打开xml2(a文件夹)为f3
for u in range(len(data2) - 14): #-14是因为最后一行
f3.write(data2[u]) #重写除最后一行</annotation>外的所有字符
f3.write('\n') #另起一行,等下接着写
for v in range(len(data1) - 1):
if data1[v] == "\t<object>\n": #找出列表data1(b文件夹)中\t<object>\n所在的行V \t是tab的意思,就是空4格,\n是换行。\t<object>\n为我们做标注的标签开头
break #找到v后终止循环,这个很重要,不终止的话b中文件有多个标签的话,后面的标签会复制多次
for r in range(v, len(data1)):
f3.write(data1[r]) #将f1(b文件夹)中的第v行到最后一行全部写入f3中
#f3.write('</annotation>\n')
f3.close() #关闭打开的f3
if all_list2[x] not in all_list1: #如果b中文件在a中没有
xml3 = dir2 + all_list2[x]
shutil.copy(xml3, dir1) ##直接把b文件拷贝到a中,名字不变
print('请勿重复执行,否则会多次写入b文件中标签')