Kinaconの技術ブログ

Ubuntuはじめました。

python Pascal VOC の Annotationデータ(XML)を解析する

f:id:m-oota-711:20190126141007p:plain

Pascal VOCのAnnotationデータから必要な情報を抜き出したときの備忘録

作業内容

  • サンプルデータより以下のデータを取得する
  • <filename>のtextを取得する
  • <size><width><height>のtextを取得する
  • <object><name>のtextが"person"の場合のみ<bndbox>の各tagのtextを取得する

目次

サンプルデータ

  • 000001.xml
<annotation>
    <folder>VOC2007</folder>
    <filename>000001.jpg</filename>
    <source>
        <database>The VOC2007 Database</database>
        <annotation>PASCAL VOC2007</annotation>
        <image>flickr</image>
        <flickrid>341012865</flickrid>
    </source>
    <owner>
        <flickrid>Fried Camels</flickrid>
        <name>Jinky the Fruit Bat</name>
    </owner>
    <size>
        <width>353</width>
        <height>500</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>dog</name>
        <pose>Left</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>48</xmin>
            <ymin>240</ymin>
            <xmax>195</xmax>
            <ymax>371</ymax>
        </bndbox>
    </object>
    <object>
        <name>person</name>
        <pose>Left</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>8</xmin>
            <ymin>12</ymin>
            <xmax>352</xmax>
            <ymax>498</ymax>
        </bndbox>
    </object>
</annotation>

xml解析の方法

  • xml.etree.ElementTreeをimportする
  • parseでxmlファイルを解析する
  • getroot()で解析結果を取得する
#! /usr/bin/python3

import xml.etree.ElementTree as ET

# XMLファイルを解析
tree = ET.parse('000001.xml')

# 解析結果を取得
annotation = tree.getroot()

xmlファイルを見て配列で要素へアクセスする

  • annotationの子ノードにfilename、size、objectがある
  • filenameは1番目、sizeは4番目、objectは6番目以降である
  • sizeのheightの要素にアクセスしたいならばannotation[4][1].textでOK。
# textを取得
filename = annotation[1].text
size = [annotation[4][0].text, annotation[4][1].text]

bndboxs = []
for i in range(6,len(annotation)):
    obj_names = annotation[i][0]    
    bndbox_tags = annotation[i][4]

    if obj_names.text == "person":
        bndbox = [bndbox_tags[n].text for n in range(4)]
        bndboxs.append(bndbox)

print(filename)
print(size)
print(bndboxs)
000001.jpg
['353', '500']
[['8', '12', '352', '498']]

tagを検索する方法

主な使い方だけ記載。配列でアクセスするほうがやりやすかったので・・・

  • find() : 最初の子ノードを検索
# find() : 最初の子ノードを検索
filename = annotation.find('filename').text

## 最初の子要素ではないのでエラーになる
width = annotation.find('width').text
  • findall() : 子要素をListで返す
for objects in annotation.findall('object'):
    obj_name = objects.find('name').text
    print(obj_name)
dog
person
  • iter() : 現在の要素とそれ以下のすべての要素を、文書内での出現順 (深さ優先順) でイテレートする
# すべてのタグを表示
for itr in annotation.iter('*'):
    print(itr.tag)

# 深い階層のtextを表示
for w in annotation.iter('width'):
    print(w.text)  

以上