我们用神经网络读取图片时,dataloader需要返回图片和标签,目标检测的标签可能相对分类麻烦一些,这里以Pascal voc数据集为例,参考Gluoncv的实现,给出xml标签处理的简单教程
1.定义类别和index_map
import numpy as np
import xml.etree.ElementTree as ET
CLASSES = ('aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car',
'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike',
'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')
index_map = dict(zip(CLASSES, range(len(CLASSES))))
print(index_map)
2.初步解析整图
anno_path='./001234.xml'
tree = ET.parse(anno_path)
root = tree.getroot()
size=root.find('size')
width = float(size.find('width').text)
height = float(size.find('height').text)
print(width,height)
out:
260.0 500.0
3.具体解析
#label验证函数
def validate_label(xmin, ymin, xmax, ymax, width, height):
"""Validate labels."""
assert 0 <= xmin < width, "xmin must in [0, {}), given {}".format(width, xmin)
assert 0 <= ymin < height, "ymin must in [0, {}), given {}".format(height, ymin)
assert xmin < xmax <= width, "xmax must in (xmin, {}], given {}".format(width, xmax)
assert ymin < ymax <= height, "ymax must in (ymin, {}], given {}".format(height, ymax)
label=[]
for obj in root.iter('object'):
difficult = int(obj.find('difficult').text)
cls_name = obj.find('name').text.strip().lower()
if cls_name not in CLASSES:
continue
cls_id = index_map[cls_name]
xml_box = obj.find('bndbox')
xmin = (float(xml_box.find('xmin').text) - 1)
ymin = (float(xml_box.find('ymin').text) - 1)
xmax = (float(xml_box.find('xmax').text) - 1)
ymax = (float(xml_box.find('ymax').text) - 1)
try:
validate_label(xmin, ymin, xmax, ymax, width, height)
except AssertionError as e:
raise RuntimeError("Invalid label at {}, {}".format(anno_path, e))
label.append([xmin, ymin, xmax, ymax, cls_id, difficult])
label=np.array(label)
print(label)
Output:
[[ 69. 13. 181. 442. 14. 0.]
[ 32. 166. 189. 499. 14. 0.]
[ 0. 424. 61. 474. 11. 0.]
[ 2. 279. 70. 383. 19. 0.]]
4.xml文件
下面内容存为001234.xml
<annotation>
<folder>VOC2007</folder>
<filename>001234.jpg</filename>
<source>
<database>The VOC2007 Database</database>
<annotation>PASCAL VOC2007</annotation>
<image>flickr</image>
<flickrid>338514152</flickrid>
</source>
<owner>
<flickrid>bensalem5g</flickrid>
<name>Brian</name>
</owner>
<size>
<width>260</width>
<height>500</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>person</name>
<pose>Frontal</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>70</xmin>
<ymin>14</ymin>
<xmax>182</xmax>
<ymax>443</ymax>
</bndbox>
</object>
<object>
<name>person</name>
<pose>Frontal</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>33</xmin>
<ymin>167</ymin>
<xmax>190</xmax>
<ymax>500</ymax>
</bndbox>
</object>
<object>
<name>dog</name>
<pose>Right</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>1</xmin>
<ymin>425</ymin>
<xmax>62</xmax>
<ymax>475</ymax>
</bndbox>
</object>
<object>
<name>tvmonitor</name>
<pose>Unspecified</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>3</xmin>
<ymin>280</ymin>
<xmax>71</xmax>
<ymax>384</ymax>
</bndbox>
</object>
</annotation>
5.Github
https://github.com/JackwithWilshere/Useful_scrips/blob/master/xml.ipynb
6.参考资料
https://github.com/dmlc/gluon-cv
https://docs.python.org/3.5/library/xml.etree.elementtree.html#module-xml.etree.ElementTree