python文件處理:解析.xml文件

XML(eXtensible Markup Language)指可擴展標記語言,被設計用來傳輸和存儲數據,已經日趨成爲當前許多新生技術的核心,在不同的領域都有着不同的應用。它是web發展到一定階段的必然產物,既具有SGML的核心特徵,又有着HTML的簡單特性,還具有明確和結構良好等許多新的特性。

在做目標檢測手工標註數據集的時候,通常會把標註的目標位置信息寫入一個.xml文件,但在檢查數據和數據清洗的時候,面對一堆座標數據很難對標註的準確性進行檢查,所以通常需要對xml文件進行解析,讀出其中保存的目標和目標的一些信息。
需要解析的xml文件如下

<annotation>
  <folder>Images</folder>
  <filename>00001</filename>
  <path>E:\Images\00001.jpg</path>
  <source>
    <database>Unknown</database>
  </source>
  <size>
    <width>432</width>
    <height>495</height>
    <depth>3</depth>
  </size>
  <segmented>0</segmented>
  <object>
    <name>mirror</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>3</xmin>
      <ymin>159</ymin>
      <xmax>52</xmax>
      <ymax>202</ymax>
    </bndbox>
  </object>
  <object>
    <name>mirror</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>370</xmin>
      <ymin>134</ymin>
      <xmax>427</xmax>
      <ymax>179</ymax>
    </bndbox>
  </object>
  <object>
    <name>glass</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>56</xmin>
      <ymin>102</ymin>
      <xmax>373</xmax>
      <ymax>224</ymax>
    </bndbox>
  </object>
  <object>
    <name>light</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>29</xmin>
      <ymin>325</ymin>
      <xmax>114</xmax>
      <ymax>389</ymax>
    </bndbox>
  </object>
  <object>
    <name>light</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>322</xmin>
      <ymin>305</ymin>
      <xmax>405</xmax>
      <ymax>372</ymax>
    </bndbox>
  </object>
</annotation>

Ok ,從結構上,它很像我們常見的HTML超文本標記語言。但他們被設計的目的是不同的,超文本標記語言被設計用來顯示數據,其焦點是數據的外觀。它被設計用來傳輸和存儲數據,其焦點是數據的內容。

那麼它有如下特徵:

首先,它是有標籤對組成:
<aa></aa>
標籤可以有屬性:<aa id=’123’></aa>
標籤對可以嵌入數據:<aa>abc</aa>
標籤可以嵌入子標籤(具有層級關係):

<aa>
     <bb></bb>
</aa>

上面的xml文件保存了目標的名字:name和四個座標(xmin, ymin, xmax, ymax),使用python對其進行解析。

#coding=utf-8
import  xml.dom.minidom

#打開xml文檔
dom = xml.dom.minidom.parse('abc.xml')

#得到文檔元素對象
root = dom.documentElement
print root.nodeName
print root.nodeValue
print root.nodeType
print root.ELEMENT_NODE

mxl.dom.minidom 模塊被用來處理xml文件,所以要先引入。

xml.dom.minidom.parse() 用於打開一個xml文件,並將這個文件對象dom變量。

documentElement 用於得到dom對象的文檔元素,並把獲得的對象給root

每一個結點都有它的nodeName,nodeValue,nodeType屬性。

nodeName爲結點名字。

nodeValue是結點的值,只對文本結點有效。

nodeType是結點的類型。catalog是ELEMENT_NODE類型

現在有以下幾種:
‘ATTRIBUTE_NODE’
‘CDATA_SECTION_NODE’
‘COMMENT_NODE’
‘DOCUMENT_FRAGMENT_NODE’
‘DOCUMENT_NODE’
‘DOCUMENT_TYPE_NODE’
‘ELEMENT_NODE’
‘ENTITY_NODE’
‘ENTITY_REFERENCE_NODE’
‘NOTATION_NODE’
‘PROCESSING_INSTRUCTION_NODE’
‘TEXT_NODE’

NodeTypes - 有名常數

對於上文列出的xml文件,筆者使用瞭如下腳本,供讀者進行參考,可根據自己的需要修改。

#! /usr/bin/env python
#coding = utf-8

from xml.dom.minidom import parse
import xml.dom.minidom
from PIL import Image, ImageDraw
import os
import ImageFont


xml_path = '/Users/Lee/Desktop/check_xml/experiments/xml/'
filelists = os.listdir(xml_path)
filelists.pop(0)

img_path = '/Users/Lee/Desktop/check_xml/experiments/images/'
save_path = '/Users/Lee/Desktop/check_xml/experiments/check_img/'
num = 0
for file in filelists:
    xml_file_path = os.path.join(xml_path+file)
    DOMTree = xml.dom.minidom.parse(xml_file_path)
    Data = DOMTree.documentElement
    img_name_tmp = Data.getElementsByTagName("filename")
    img_name = img_name_tmp[0].childNodes[0].data
    Objects = Data.getElementsByTagName("object")

    xmin_1 = []
    ymin_1 = []
    xmax_1 = []
    ymax_1 = []
    name_1 = []

    for object in Objects:
        name = object.getElementsByTagName('name')[0]
        name_1.append(name.childNodes[0].data)

        xmin = object.getElementsByTagName('xmin')[0]
        xmin_1.append(int(xmin.childNodes[0].data))

        ymin = object.getElementsByTagName('ymin')[0]
        ymin_1.append(int(ymin.childNodes[0].data))

        xmax = object.getElementsByTagName('xmax')[0]
        xmax_1.append(int(xmax.childNodes[0].data))

        ymax = object.getElementsByTagName('ymax')[0]
        ymax_1.append(int(ymax.childNodes[0].data))

    img = Image.open(os.path.join(img_path+img_name+'.jpg'))
    num_object = len(name_1)
    for i in range(num_object):
        x_text = (xmax_1[i] - xmin_1[i]) * 0.15 + xmin_1[i]
        y_text = ymin_1[i] - 25
        draw_name = ImageDraw.Draw(img)
        font1 = ImageFont.truetype("times_New_Roman.ttf",24)
        draw_name.text((x_text, y_text), name_1[i], fill= (255,0,0), font = font1)
        draw_rect = ImageDraw.Draw(img)
        draw_rect.rectangle([(xmin_1[i], ymin_1[i]), (xmax_1[i], ymax_1[i])],outline=(255,0,0))
    img.save(os.path.join(save_path + img_name + '.jpg'))
    num = num + 1
    if num % 500 == 0:
        print num

上述腳本可以把xml保存的名字和位置信息在原圖上反映出來,用以檢查手工標註數據的準確性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章