接着上一篇的文章继续制作自己的数据集,由于需要将数据集弄成与VOC 2007数据集一样的格式,需要自己手动标注数据,根据网上前辈的经验,这里使用了labelImg,版本用了windows_v1 .7.0,操作简单方便。使用该软件进行标注后将直接生成以与图片名称相同的.XML文件。
以其中的000009.xml文件内容格式为例,这里是我自己标注后形成的xml文件,和voc 2007的数据标注后形成的xml文件略有差别
<annotation>
<folder>datajpg</folder> #这里是我自己的图像数据保存位置
<filename>000009.jpg</filename> #图像名称
<path>E:\datajpg\000009.jpg</path>
<source>
<database>Unknown</database>
</source>
<size>
<width>512</width>
<height>512</height>
<depth>3</depth>
</size>
<segmented>0</segmented>
<object>
<name>burn</name>
<pose>Unspecified</pose>
<truncated>1</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>149</xmin>
<ymin>237</ymin>
<xmax>470</xmax>
<ymax>512</ymax>
</bndbox>
</object>
<object>
<name>drop piece</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>418</xmin>
<ymin>8</ymin>
<xmax>502</xmax>
<ymax>218</ymax>
</bndbox>
</object>
</annotation>
voc 2007的标注内容格式如下
<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>
由于是新手,缺少经验,标注完自己的数据才发现和标准的数据有点差别,自己标注的和标准数据给的主要差别在于foldername的名称上。于是还需要对xml文件进行批量处理操作,更改这一名字。
以下代码参考了大神写的蟒蛇源码,表示这里感谢https://saicoco.github.io/object-detection-4/
import glob
xml_path = '.data\\Annotations\\'
items = glob.glob(xml_path + '*.xml')
for item in items:
dom = xdm.parse(item)
root = dom.documentElement
folder_dom = root.getElementsByTagName('folder')
folder_dom[0].firstChild.data = 'VOC2007'
img_dom = root.getElementsByTagName('filename')
img_dom[0].firstChild.data = img_dom[0].firstChild.data + '.jpg'
## 将结果写入xml文件
## writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
##第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
## dom.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
with open(item, 'w') as f:
dom.writexml(f,encoding='utf-8')
参照大神的源码,我想自己顺便练练手,于是按照思路写了一个,就当练习编程了。
# -*- coding: utf-8 -*-
"""
Created on Sun Jul 29 21:22:56 2018
@author: jcli
"""
import xml.dom.minidom as xdm
import os
xml_path = 'E:\\Annotations'
filelist = os.listdir(xml_path)
for file in filelist:
with open(os.path.join(xml_path,file),'r',encoding='utf8') as fh:
dom = xdm.parse(fh)
root = dom.documentElement
folder_dom = root.getElementsByTagName('folder')
folder_dom[0].firstChild.data = 'VOC2007'
with open(os.path.join(xml_path,file),'w') as f:
dom.writexml(f,encoding = 'utf-8')
将源码中路径改成自己的文件夹路径,运行上面两个任意一段源码即可实现更改的XML文件中的文件夹名称。
DOM(Document Object Model)文件对象模型,python在利用DOM解析XML文件时会将XML数据在内存中解析成一个树,通过对树的操作来操作XML。
tree = xml.dom.minidom.parse('000012.xml') #用parse()获取dom对象
root = tree.documentElement #获取根节点
file_name = root.getElementsByTagName('filename') #由根节点通过节点名称获取对应的子节点
file_name.childNodes[0].data = ‘newdata’ #获取对应子节点的数据并赋予新值
with open('000012.xml','w') as f: #对xml文件进行写操作
root.writexml(f,encoding = 'utf-8')
关于更详细的DOM写入和解析xml可参考文章:https://www.cnblogs.com/wcwnina/p/7222180.html