![60ca336e6e5439d2520a4cb62f560651.png](https://i-blog.csdnimg.cn/blog_migrate/fc111d4f451b121272239b588dc5c025.jpeg)
1. 什么是XML?
xml是格式化的纯文本,用于存储数据和格式。
2. DOM是什么?
DOM是xml的一种解析方法(此外还包括SAX等,此处不提),它将xml文件抽象成为一个树型结构,这棵树个各个树叶就是节点。也就是说,DOM 定义了所有文档元素的对象和属性,以及访问它们的方法(接口)。
DOM的主要性质:
- 文档是一个文档节点,即根节点,对象树型是domTree.documentElement
- 每个 XML 标签是一个元素节点,元素节点接口方法见链接, 主要包括的方法和属性有:
- getElementsByTagName():根据tag获取elements
- getAttributeNode():获取特定属性值
- childNodes:子节点的nodelist
- ...
- 包含在 XML 元素中的文本是文本节点
- 每一个 XML 属性是一个属性节点
- 注释属于注释节点
3. 使用dom解析xml例程
- 例程说明
“博主用了一个图像标注系统CVAT进行车道线的标注,如下图,系统输出的标注结果就是一个xml文件。我们的label有6类,'left_3', 'left_2', 'left_1', 'right_1', 'right_2', 'right_3'。我们的工作就是解析xml文件。”
![af2b09d20780d68697658f9ab952fc23.png](https://i-blog.csdnimg.cn/blog_migrate/7106ff38e5baa569b9a5dab5e2adbcca.jpeg)
我的xml文件如下所示, 可以复制下来进行代码测试。
<?xml version="1.0" encoding="utf-8"?>
<annotations>
<version>1.1</version>
<meta>
<task>
<id>71</id>
<name>front_lane_normal_bright_20200826_1</name>
<size>1455</size>
<mode>annotation</mode>
<overlap>0</overlap>
<bugtracker></bugtracker>
<created>2020-08-26 02:13:44.099919+00:00</created>
<updated>2020-08-28 08:57:13.943460+00:00</updated>
<start_frame>0</start_frame>
<stop_frame>1454</stop_frame>
<frame_filter></frame_filter>
<z_order>False</z_order>
<labels>
<label>
<name>left_3</name>
<attributes>
</attributes>
</label>
<label>
<name>left_2</name>
<attributes>
</attributes>
</label>
<label>
<name>left_1</name>
<attributes>
</attributes>
</label>
<label>
<name>right_1</name>
<attributes>
</attributes>
</label>
<label>
<name>right_2</name>
<attributes>
</attributes>
</label>
<label>
<name>right_3</name>
<attributes>
</attributes>
</label>
</labels>
<segments>
<segment>
<id>221</id>
<start>0</start>
<stop>19</stop>
<url>http://xxx.xxx.xxx.xxx:8080/?id=221</url>
</segment>
</segments>
<owner>
<username>test</username>
<email>test@test.tech</email>
</owner>
<assignee>
<username>test</username>
<email>test@test.tech</email>
</assignee>
</task>
<dumped>2020-08-30 09:49:39.875576+00:00</dumped>
</meta>
<image id="0" name="00.jpg" width="1280" height="1080">
<polyline label="right_2" occluded="0" points="660.79,372.67;874.57,473.35;1280.00,681.03">
</polyline>
<polyline label="right_1" occluded="0" points="604.04,364.96;723.04,545.20;1064.02,1074.54">
</polyline>
<polyline label="left_3" occluded="0" points="513.18,378.36;271.53,515.26;0.00,681.53">
</polyline>
<polyline label="left_2" occluded="0" points="563.04,366.94;360.00,644.00;64.83,1080.00">
</polyline>
<polyline label="left_1" occluded="0" points="568.56,365.28;437.94,580.75;145.64,1080.00">
</polyline>
</image>
</annotations>
对应的原始图像在下面
![1b19a727f1448888d8b2fe03cab9607d.png](https://i-blog.csdnimg.cn/blog_migrate/ccba525254dde2f36cbd31e68c695636.jpeg)
2. xml文件说明
为了方便可以使用浏览器打开,是下面这样的格式。可以看到,根节点就是annotations, 其子节点包括version、meta、image等等,其中meta->task->labels是我们规定的标注规范中的label类别,包括"left_3"...."right_3"等。另外各个image节点就是我们对应的每一张图像的标注结果,子元素节点包括多个polyline,每个polyline就是一条车道线,采用str类型的点对表示。另外,image节点中包含了"id","name","width","height"等等属性节点,我们可以通过"name"属性节点找到对应的图像名称。
![e42e2d4067292e6c3646c90de59be6b8.png](https://i-blog.csdnimg.cn/blog_migrate/522db8deb01b267c730afa9b72e2f465.jpeg)
3. 上代码
#-*-coding:utf-8-*-
from xml.dom.minidom import parse # 导入dom相应的模块
import cv2 # 用于图像的显示
import os
import numpy as np
def parsingLabel(xml_path):
"""
parsing the cvat xml file
:return:
"""
# 一些参数的设置
annotation_labels = []
annotation_label_dicts = {
"left_1":0,
"left_2":1,
"left_3":2,
"right_1":3,
"right_2":4,
"right_3":5
}
annotation_label_colors = {
"left_1":(255, 0, 0),
"left_2":(0, 255, 0),
"left_3":(0, 0, 255),
"right_1":(125, 125, 125),
"right_2":(125, 200, 200),
"right_3":(200, 100, 200)
}
img_dir = "/home/cjs/Downloads/data" # 设置加载的图像路径
# 获取dom树
domTree = parse(xml_path)
rootNode = domTree.documentElement # 获取文档根元素
# print(rootNode.nodeName)
# 根据名称获取version节点
version = rootNode.getElementsByTagName('version')[0] # 注意返回值是nodelist
# 需要注意的是,xml中每一个元素都要看成一个节点,因此想得到节点的值,需要通过childNodes属性得到
# 子节点,然后通过nodeValue得到其节点值。
print("the version of the cvat is {}".format(version.childNodes[0].nodeValue))
# 获取meta节点(我们这里只有一个meta节点,因此取nodelist的第0个值)
meta = rootNode.getElementsByTagName("meta")[0]
task = meta.getElementsByTagName("task")[0] # 获取task子节点
# 获取所有的label
task_labels = task.getElementsByTagName("labels")[0].getElementsByTagName("label")
for task_label in task_labels:
task_label_one = task_label.getElementsByTagName("name")[0]
task_label_one_value = task_label_one.childNodes[0].nodeValue
# print(task_label_one_value)
annotation_labels.append(task_label_one_value)
# 解析所有的image标注结果
img_labels = rootNode.getElementsByTagName("image")
for img_label in img_labels:
# 获取并加载原始图像,读者可以自己照一张1280*1080大小的图片进行测试
img_label_name = img_label.getAttribute("name").split("/")[-1]
img_path = os.path.join(img_dir, img_label_name)
img = cv2.imread(img_path, -1)
img_width = int(float(img_label.getAttribute("width").strip()))
img_height = int(float(img_label.getAttribute("height").strip()))
# 获取所有image标注的车道线结果elements的值
img_label_totals = img_label.getElementsByTagName("polyline")
# 对所有标注结果进行转换
for img_label_one in img_label_totals:
label_type_name = img_label_one.getAttribute("label")
label_type_index = annotation_label_dicts[label_type_name]
label_points = img_label_one.getAttribute("points")
label_points = label_points.strip().split(';')
tmp_line_pts = [label_type_name]
for ii in range(len(label_points)):
label_point = label_points[ii]
label_point = label_point.split(",")
pt_x = int(float(label_point[0]))
pt_x = np.clip(pt_x, 0, img_width-1)
pt_y = int(float(label_point[1]))
pt_y = np.clip(pt_y, 0, img_height-1)
cv2.circle(img, (pt_x, pt_y), 20, annotation_label_colors[label_type_name], -1)
tmp_line_pts.append([pt_x, pt_y])
print("finished one label converting named {}".format(img_path))
cv2.imshow("img", img)
cv2.waitKey(0)
if __name__ == "__main__":
parsingLabel("./annotations.xml")
运行脚本结果如下图所示,各个车道线分别由不同的点集组成。
![c178759f278fac16cc6483124db801a8.png](https://i-blog.csdnimg.cn/blog_migrate/d0aa225f2348fbfc2a27fc256276e6a2.jpeg)
总结
DOM将XML看成一个节点,节点类型包括元素节点,文本节点等,解析过程就是利用element类的各种属性和方法来得到想要的值的过程。
码字不易,觉得不错的看官就点个赞再走吧~
参考文献:
- xml dom课程,w3school
- xml中element的属性和方法
- cvat图像标注系统