1.主要内容和目的
本文主要记录下自己将xml文件中有用的数据提取至txt的过程。在查找代码时发现,大都复制粘贴的代码,不仅冗余,而且晦涩难懂,于是自己整理了一套代码。不多说,直接图解。
2.我的xml文件如下:
大家的xml文件大同小异,可以耐心看完,自己就会改了。
<annotation> <folder>UAV_data</folder> <filename>anju _19.jpg</filename> <source> <database>The UAV autolanding</database> <annotation>UAV AutoLanding</annotation> <image>flickr</image> <flickrid>NULL</flickrid> </source> <owner> <flickrid>NULL</flickrid> <name>ChaojieZhu</name> </owner> <size> <width>1080</width> <height>1080</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>parkset</name> <pose>Unspecified</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>0.0</xmin> <ymin>422.0</ymin> <xmax>347.1904761904762</xmax> <ymax>626.0</ymax> </bndbox> <keypoints> <x0>323.0</x0> <y0>626.0</y0> <x1>347.1904761904762</x1> <y1>463.4920634920635</y1> <x2>0.0</x2> <y2>422.0</y2> <x3>0.0</x3> <y3>589.0</y3> </keypoints> </object> <object> <name>wheel_stopper</name> <pose>Unspecified</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>782.0408163265306</xmin> <ymin>514.2857142857142</ymin> <xmax>986.937984496124</xmax> <ymax>658.1395348837209</ymax> </bndbox> <keypoints> <x0>793.0612244897959</x0> <y0>514.2857142857142</y0> <x1>782.0408163265306</x1> <y1>645.3061224489795</y1> <x2>976.8604651162791</x2> <y2>658.1395348837209</y2> <x3>986.937984496124</x3> <y3>537.2093023255813</y3> </keypoints> </object> <object> <name>wheel_stopper</name> <pose>Unspecified</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>765.8959537572255</xmin> <ymin>660.1156069364162</ymin> <xmax>977.4193548387096</xmax> <ymax>812.9032258064516</ymax> </bndbox> <keypoints> <x0>780.9248554913295</x0> <y0>660.1156069364162</y0> <x1>765.8959537572255</x1> <y1>795.9537572254335</y1> <x2>954.8387096774193</x2> <y2>812.9032258064516</y2> <x3>977.4193548387096</x3> <y3>673.5483870967741</y3> </keypoints> </object> <object> <name>wheel_stopper</name> <pose>Unspecified</pose> <truncated>1</truncated> <difficult>0</difficult> <bndbox> <xmin>9.418604651162795</xmin> <ymin>437.2093023255814</ymin> <xmax>66.21621621621621</xmax> <ymax>483.3333333333333</ymax> </bndbox> <keypoints> <x0>62.61261261261261</x0> <y0>483.3333333333333</y0> <x1>66.21621621621621</x1> <y1>442.79279279279274</y1> <x2>11.74418604651163</x2> <y2>437.2093023255814</y2> <x3>9.418604651162795</x3> <y3>472.09302325581393</y3> </keypoints>
我是想得到 filename 中的anju_19.jpg以及 keypoints中x0 y0 x1 y1这些数据点,并在txt中间断空格保存。那么问题来了,如何解析呢,下面付了代码并做出了解释。
2.我的代码如下:
我知道你最想要的是代码,那么代码如下,。。。。
等等确定不看下 下面解释来理解一下原理嘛。 保你看懂哦,看懂看到任何xml转格式和提取再也不怕啦。
#from os import listdir, getcwd #from os.path import join import cv2 import os from xml.etree.ElementTree import parse xmlfilepath='D:\\destop\\dst\\xml\\' #你的xml文件夹路径,不是xml文件,批量处理时用 total_xml = os.listdir(xmlfilepath)#遍历xml文件 for xml in total_xml: xml_path=os.path.join(xmlfilepath,xml)#xml的全路径,也就是文件的路径 print(xml_path) tree = parse(xml_path) #获取ElementTree root = tree.getroot() #获取根元素 filename = root.findtext('filename')#提取到了xml对应的 filename的名字 print('filename:',filename) for obj in root.iter('object'):#看上面xml文件可知我想要的keypoints在object这个标签下,而且有很多object ,因此我要遍历object print('obj:',str(obj)) cls = obj.find('name').text#将解析得到该keypoints下 name中的标签,也就是wheel_stopper类 print('cls:',cls) if cls=='wheel_stopper': #由与还有标签parkset类 而我只想要wheel_stopper类别下的x0 y0.... xmlbox = obj.find('keypoints') #此时得到了想要的点x0,y0,x1,y1, b = ((xmlbox.find('x0').text), (xmlbox.find('y0').text), ( xmlbox.find('x1').text), (xmlbox.find('y1').text)) with open('D:\\destop\\dst\\1.txt','a') as f:#不用创建,自己存一个路径 我这里是1.txt 那你呢。。你定吧 f.write(str(filename)) print("b:",b[0]) for i in range(len(b)): f.write(' ') f.write(str(b[i])) f.write('\n')
重要的要理解
root = tree.getroot() #获取根元素 filename = root.findtext('filename')#提取到了xml对应的 filename的名字
上述代码root就是将xml加载解析了,而filename(上图红色箭头指向)相当于一级目录,这个一级目录下就他自己,用root.findtext(‘filename’)即可解析得到。
3 通俗讲解
暂且通俗易懂的叫object为一级目录,想得到的x0,y0,x1,y1在object下的keypoints中,
这相当于keypoints是二级目录,如果想要得到Xmin Ymin就将 keypoints换为bndbox即可。
看上图蓝色箭头知道object不止一个呀,咋办哦, 那就遍历所有object,于是下面代码相当于遍历了一遍一级目录 ‘object’,于是可以可以得到二级目录运用obj.find(‘name’)这里name可以替换成任意二级目录。
敲黑板啦,你的name应该是你要的类别,你的name可能不是我的wheel_stopper,可能是car ,person,dog等一些类别标签,注意替换哦。这里我只想要wheel_stopper,所以你想要啥标签可以自己写下,也可以找我帮你嘛
for obj in root.iter('object'):#看上面xml文件可知我想要的keypoints在object这个标签下,而且有很多object ,因此我要遍历object print('obj:',str(obj)) cls = obj.find('name').text#将解析得到该keypoints下 name中的标签,也就是wheel_stopper类 print('cls:',cls) if cls=='wheel_stopper': #由与还有标签parkset类 而我只想要wheel_stopper类别下的x0 y0.... xmlbox = obj.find('keypoints') #此时得到了想要的点x0,y0,x1,y1, b = ((xmlbox.find('x0').text), (xmlbox.find('y0').text), ( xmlbox.find('x1').text), (xmlbox.find('y1').text))
运用 xmlbox = obj.find(‘keypoints’) #此时得到了想要的点x0,y0,x1,y1,
运用xmlbox.find(‘x0’).text),就可以得到X0数据,以此类推。
with open('D:\\destop\\dst\\1.txt','a') as f:#不用创建,自己存一个路径 我这里是1.txt 那你呢。。你定吧
这里的目的是创建一个txt存取 提取的x0,y0等
4 结果
最终得到了数据如下图:
我这个文件夹就有一个xml文件 所以只有一个名字,并且没有将数据写在一行,你可以更改的哦,我后面需要的时候更改啦
怎么样,不知道讲清楚了没。
如果对你有帮助,还希望一键三连啊。
欢迎被代码困住的 被debug缠身的小伙伴交流解决,视觉相关代码,单目测距,论文撰写,(yolo,presacn,matlab,c++)皆可交流哦------------------------!