(圖片來源:digitalinformationworld)

在深度學習建立自己的模型中,收集訓練資料向來是費時的一個大工程,其中,將網路上的 dataset 或是 database 下載下來的訓練資料進行 annotation 的格式轉換也成了無法避免的過程,所以筆者要分享的就是透過 python 建立 VOC dataset annotation 的 XML 檔

筆者在建立之前,前置作業的流程如下 :
Matlab 讀取 Dataset A 的 annotation(.m)  找出需要的屬性值並輸出成 txt  讀取 txt 並使用 python 建立 XML (即本文主題)

下圖是筆者想做出的 VOC dataset annotation 格式(裡面的屬性意義,請自行下載 documentation 瞭解) :




轉成樹狀圖如下,建立 xml 就跟建立樹狀圖或是 data structure 的 tree 一樣,定義節點間的父子關係,一層層的建立起來



首先,import xml.dom.minidom 以使用所需函式
關鍵 function : createElement, createTextNode, appendChild
  • 使用 createElement 來建立tag
  • 使用 createTextNode 來填入 tag 中的 string內容
  • 使用 appendchild 來建立上下(父子)結構
假設我們想建構出如下的 xml :
<annotation>
    <folder>Bal Laedi</folder>
<annotation>


code 就會如下圖所示 :
import xml.dom.minidom

#建立空的樹狀圖,可以想像成初始化XML
doc = xml.dom.minidom.Document()

#建立annotation tag
root = doc.createElement('annotation')

#將annotation tag放入樹狀圖中
doc.appendChild(root)

#建立folder tag
folderElem = doc.createElement('folder')

#建立folder tag中寫入內容Bal Laedi
folderElem.appendChild(doc.createTextNode('Bal Laedi'))

#將folder tag設定為annotation的下層
root.appendChild(folderElem)


接下來就差寫入檔案,writexml 除了指定寫入的檔案,還能設定縮排的方式 :
f = open('output.xml', 'w')
doc.writexml(f, indent='\t',  addindent='\t',  newl= '\n')

最後,完整的 code 如下 :
  • 以下的 function 除了 filename, size, bndbox 之外,其他的屬性值都是寫死的
  • 這裡的 argument txtfile 是用作讀取 txt 檔案中記錄的 xmin, ymin, xmax, ymax 值
def txtToXML(txtfile,imgpath,xmlpath):
    doc = xml.dom.minidom.Document()
    root = doc.createElement('annotation')
    doc.appendChild(root)
    
    folderElem = doc.createElement('folder')
    folderElem.appendChild(doc.createTextNode('newImage'))
    root.appendChild(folderElem)
    
    filenameElem = doc.createElement('filename')
    tmp = files.split('.',1)
    imgfilename = tmp[0] + ".jpg"
    filenameElem.appendChild(doc.createTextNode(imgfilename))
    root.appendChild(filenameElem)
    
    imgpth = imgpath + imgfilename
    path = doc.createElement('path')
    path.appendChild(doc.createTextNode(imgpth))
    root.appendChild(path)
    
    src = doc.createElement('source')
    db = doc.createElement('database')
    db.appendChild(doc.createTextNode('Unknown'))
    src.appendChild(db)
    root.appendChild(src)
    
    size = doc.createElement('size')
    width = doc.createElement('width')
    height = doc.createElement('height')
    depth = doc.createElement('depth')
    img = cv2.imread(imgpth)
    width.appendChild(doc.createTextNode(str(img.shape[1])))
    height.appendChild(doc.createTextNode(str(img.shape[0])))
    depth.appendChild(doc.createTextNode(str(img.shape[2])))
    size.appendChild(width);size.appendChild(height);size.appendChild(depth);
    root.appendChild(size)
    
    seg = doc.createElement('segmented')
    seg.appendChild(doc.createTextNode('0'))
    root.appendChild(seg)
    
    f = open(txtFolder + txtfile,'r')
    s = f.readline()
    obj = doc.createElement('object')
    name = doc.createElement('name')
    name.appendChild(doc.createTextNode('hand'))
    pose = doc.createElement('pose')
    pose.appendChild(doc.createTextNode('Unspecified'))
    truncated = doc.createElement('truncated')
    truncated.appendChild(doc.createTextNode('0'))
    difficult = doc.createElement('difficult')
    difficult.appendChild(doc.createTextNode('0'))
    obj.appendChild(name);obj.appendChild(pose);obj.appendChild(truncated);obj.appendChild(difficult);
    root.appendChild(obj)
        
    xy = s.split(' ',3)
    xmin = doc.createElement('xmin')
    xmin.appendChild(doc.createTextNode(xy[1]))
    ymin = doc.createElement('ymin')
    ymin.appendChild(doc.createTextNode(xy[3]))
    xmax = doc.createElement('xmax')
    xmax.appendChild(doc.createTextNode(xy[0]))
    ymax = doc.createElement('ymax')
    ymax.appendChild(doc.createTextNode(xy[2]))
    bndbox = doc.createElement('bndbox')
    bndbox.appendChild(xmin);bndbox.appendChild(ymin);bndbox.appendChild(xmax);bndbox.appendChild(ymax);
    obj.appendChild(bndbox)
    s = f.readline()
    f.close()
    
    f = open(xmlpath, 'w');
    doc.writexml(f, indent='\t', addindent='\t', newl= '\n')
    f.close()

Post a Comment

較新的 較舊