0%

数据集筛选及其xml格式的label修改

组委会先发布了一部分的数据,去年星图杯是用于飞机目标追踪的,由于今年的飞机种类和去年几乎一致(多了C919,不过后续的数据信息统计可以发现就几张,先扔掉),所以想先选出飞机的图片和xml的label来,我就写了个文件来选出飞机和对应的修改后的xml,需要考虑的时候,通过xml的objects/object/possibleresult/name来进行判别是否是飞机。由于只想留下飞机,所以需要做如下两点:

1、通过name来看是否是飞机,不是则通过一些方法删除该object
2、检测删除完后的objects是否为空,非空说明xml有飞机,保存该xml和对应的tif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
'''
把gf2021的数据集中的飞机都选出来,即一张图片中若含有飞机模型的,则选出来,同时需要修改xml文件,将
objects属性中的非飞机的object去掉,由于删除的非annotation直系节点,需要转换一下才能删除。
'''
import os
import numpy as np
import scipy.misc as misc
from xml.dom.minidom import Document
import numpy as np
import copy, cv2
# import imageio
import json
import glob
import xml.etree.cElementTree as ET
from xml.etree.ElementTree import ElementTree,Element
import shutil
import re
from osgeo import gdal, gdalconst

def choose_plane(image_path, xml_path,image_save_path,xml_save_path):
plane_label = ["Boeing737","Boeing747","Boeing777","C919","A220","A321","A330","A350","ARJ21","other-airplane"]
for count, xml in enumerate(glob.glob(xml_path + '/*.xml')):#进行索引,*代表任意匹配,得到可迭代对象
#flag =0
# to avoid path error in different development platform
xml = xml.replace('\\', '/')#用/替换\\,后面的替换前面的
(_, xml_name) = os.path.split(xml)#分割。返回路径和文件名。若本身就是一个文件夹路径,则返回路径和空
#print(xml,xml_name)

img_name=xml_name.replace('.xml', '.tif')
img_path = image_path + '/' + img_name
#1. 读取xml文件
tree = ElementTree()
tree.parse(xml)
root = tree.getroot()

#A. 找到父节点
node_root = root.findall( "objects")#不能直接找object,直接找object,删掉的只是object,但是tree只能删除objects,没有用,所以进行替换

for objects_list in node_root:#遍历objects,其实只有一个
for object_list in list(objects_list):#得到object,不加list竟然无法遍历,迷惑
#print(object_list)
if object_list.find("possibleresult/name").text not in plane_label:
#print("成功移除")
objects_list.remove(object_list)
#flag = 1
#替换直系节点objects
for i,external_node in enumerate(root):
if external_node.tag == "objects":#寻找objects节点
root[i]=objects_list

if objects_list:#判断是否为空,空的list的bool属性为false.非空的为true
#if flag == 1:
# print(xml,object_list.find("possibleresult/name").text,objects_list.find("object/possibleresult/name").text)
#存储xml
xml_save=xml_save_path+"/"+xml_name
tree.write(xml_save, encoding="utf-8",xml_declaration=True)
#存储图片
shutil.copyfile(img_path, image_save_path+"/"+img_name)#将第一个参数的文件复制到第二个里面

if not os.path.exists(img_path):
print('{} is not exist!'.format(img_path))
continue

# view_bar('Conversion progress', count + 1,
# len(glob.glob(xml_path + '/*.xml')))

print('\nStatistics is complete!')

if __name__ == "__main__":
image_path=r"/emwuser/gzl/gf2021/data/FAIR1M/train/part1/images"
xml_path=r"/emwuser/gzl/gf2021/data/FAIR1M/train/part1/labelXmls"

image_save_path=r"/emwuser/gzl/gf2021/data/FAIR1M/train/part1_plane/images"
xml_save_path=r"/emwuser/gzl/gf2021/data/FAIR1M/train/part1_plane/labelXmls"

choose_plane(image_path,xml_path,image_save_path,xml_save_path)

其主体就是choose_plane,来分析一下choose_plane:

1
plane_label = ["Boeing737","Boeing747","Boeing777","C919","A220","A321","A330","A350","ARJ21","other-airplane"]

这一句是用来后续判别xml的objects/object/possibleresult/name的属性值是否是飞机的,只要判断name的属性值是否在该列表中即可。

然后循环进行读取文件夹下的xml文件,通过通过split找到文件名、文件路径,由此通过replace即可得到对应的image路径。

然后读取xml文件,代码如下,其中findall用于寻找annotation的直系子节点或者下属节点,也可以传入”objects/object”,其返回的是一个列表,列表中的元素是objects,我们知道objects只有一个,所以其实node_root[0]就是objects,用for循环也可以(本代码是用for来的)。其实我们希望删除的是object,为什么不findall(“objects/object”)呢?因为我们如果寻找object的话,的确可以很好的删除,但是删除了object后,原来的root是没变的,所以需要把删除后的替换进去,如果直接root[3]赋值我们删除后的object的话(root[3]是objects),objects就变成object了,所以这是不对的。如果我们直接寻找出来的就是objects,那么再往下找object,删除objects中的object,然后用该objects替换root中的objects,就可以完美解决。

1
2
3
4
5
6
7
8
9
img_name=xml_name.replace('.xml', '.tif')
img_path = image_path + '/' + img_name
#1. 读取xml文件
tree = ElementTree()
tree.parse(xml)
root = tree.getroot()

#A. 找到父节点
node_root = root.findall( "objects")#不能直接找object,直接找object,删掉的只是object,但是tree只能删除objects,没有用,所以进行替换

上面已经说了如何删除object了,那么删除后,需要对root中的objects进行替换,一般objects是root的第四个属性,就是root[3],但是也可能不是,所以就用到了下面这个循环了:

1
2
3
4
#替换直系节点objects
for i,external_node in enumerate(root):
if external_node.tag == "objects":#寻找objects节点
root[i]=objects_list

最后需要判断一下删除后的objects是否为空,如果空了,说明没有飞机,如果不是空(不是空的列表的bool值是true),则存储替换objects后的root和对应的tif,存储的文件夹自行指定;

1
2
3
4
5
6
7
8
if objects_list:#判断是否为空,空的list的bool属性为false.非空的为true
#if flag == 1:
# print(xml,object_list.find("possibleresult/name").text,objects_list.find("object/possibleresult/name").text)
#存储xml
xml_save=xml_save_path+"/"+xml_name
tree.write(xml_save, encoding="utf-8",xml_declaration=True)
#存储图片
shutil.copyfile(img_path, image_save_path+"/"+img_name)#将第一个参数的文件复制到第二个里面
- - - - - - - - - - - - - - 本文结束啦,感谢您的观看 - - - - - - - - - - - - - -