目标检测(四)

您所在的位置:网站首页 xml文件怎么写代码 目标检测(四)

目标检测(四)

2024-01-09 09:59| 来源: 网络整理| 查看: 265

文章目录 什么是xmlxml解析讲解一、标签介绍filename标签size标签object标签 二、xml解析的API xml单个文件的解析构建类别索引(category_id)构建xml解析代码测试

什么是xml

XML 被设计用来传输和存储数据。 XML于HTML的标签语言类似,都是使用标签来进行约束!【相对于html标签,xml标签可以自定义】 (对于上面的定义,我们简单了解一下就可以了,并不会对我们解析它有影响!) 下面展示一份简单的xml文件!(AI识虫的一份用于存储目标检测相关数据的xml文件)

刘霏霏 1.jpeg /home/fion/桌面/刘霏霏/1.jpeg Unknown 1344 1344 3 0 Leconte Unspecified 0 0 473 578 612 727 Boerner Unspecified 0 0 822 505 948 639 linnaeus Unspecified 0 0 607 781 690 842 armandi Unspecified 0 0 756 786 841 856 coleoptera Unspecified 0 0 624 488 711 554 xml解析讲解 一、标签介绍

上边的示例xml文件中,其中最主要的是filename(文件–图片名称),size(图片大小和通道数), object(就是我们需要关注的目标检测的边界框位置等)。

【再次说明,xml中的标签可以自定义,只需要满足命名规范和标签闭合即可】

标签闭合: 自中,filename就是自定义的标签,前后对账,后者添加一个 /即可命名规范: 名称可以包含字母、数字以及其他的字符 名称不能以数字或者标点符号开始 名称不能以字母 xml(或者 XML、Xml 等等)开始 名称不能包含空格

下面就对之前提到的三个部分做简要的说明!

filename标签 1.jpeg

这个标签在AI识虫中对应着每一个xml文件对应的图片名称

size标签 1344 1344 3

可以看出,size中还包含其它的内部标签,此时我们需要解析内部的数据就需要继续继续往里边查找标签——比如对width标签就对应着图片的宽度。【depth:常常表示通道数】

object标签 Leconte Unspecified 0 0 473 578 612 727

object通常就是我们目标检测中检测物体边界框所在的外层标签。 其中0,表示该物体是否检测存在困难; 更重要的是:

473 578 612 727

在bndbox标签中,包含我们检测的边界框的左上顶点(xmin, ymin) ,右下顶点(xmax, ymax)!

以上,基本上就对一份xml文件内容和确定解析标签做了一个基本的阐述。

二、xml解析的API

python中解析xml是通过操做xml库实现的!

首先导入库: import xml

具体解析xml文件是使用xml.etrre.ElementTree来构建xml解析树实现的

该APIxml.etrre.ElementTree下的parse可以快速解析xml文件 形式如下: xml.etrre.ElementTree.parse(xml_path)实现对xml_path对应的xml文件进行解析,并返回一个xml解析树对象!

此时获取的解析树还只是一个直接的数据,不能直接获取我们想要的东西,此时需要对解析树使用find(标签)来对指定标签进行查讯,并返回该标签对象,然后,再跟上一个text获取该标签的属性(注意:text针对仅含有具体字符数据的标签,如 1, 而不是1这样的复合标签)。 eg:

# xml解析树 xml_tree = xml.etrre.ElementTree.parse(xml_path) # find从解析对象中找到id标签对象,然后使用text属性,获取xml中该标签对应的数据 id_data = xml_tree.find('id').text # 此时返回的数据是str,如果是数值,可以使用int/float进行转换

总结起来,xml解析最主要的操作就是:

使用xml.etrre.ElementTree.parse(xml_path)创建一个初始的xml树对象;然后对返回的树对象使用find进行标签查找;找到所需要的子标签时,再使用text属性进行读取即可! xml单个文件的解析

在解析文件前,我们来确定一下分析xml中所要关注的标签。 在AI识虫的xml中,我们需要关注的标签:

filename : 解析出当前xml对应的图片文件名size -> width , height, depth : 解析出图片的大小和通道数objeck -> bndbox : 解析出objeck下的bbox数据difficult : 解析当前bbox是否存在识别困难

接下来就从以上四个方面进行解析——

构建类别索引(category_id)

模型的输出与损失计算都是数值的,而xml中有时候会出现category(类别)名称,需要进行转换! 因此,我们就AI识虫数据集中的xml所存在的类别进行整理:

# 其对应的cotegory有7种 INSECT_NAMES = ['Boerner', 'Leconte', 'Linnaeus', 'acuminatus', 'armandi', 'coleoptera', 'linnaeus']

我们就对以上的类别设置顺序索引,从Boerner-0, Leconte-1, … , linnaeus-6进行映射! 这里利用字典来存取这样的映射,方便我们后边解析出xml中的类别时,可以使用key直接获取类别的id! 构建字典的函数如下:

# 构造类别对应的索引字典 def get_insect_name(): """获取类别索引字典 return a dict, {'Boerner': 0, 'Leconte': 1, 'Linnaeus': 2, 'acuminatus': 3, 'armandi': 4, 'coleoptera': 5, 'linnaeus': 6 } """ insect_category2id = {} # 从类别到id的一个映射 for i, item in enumerate(INSECT_NAMES): # 利用enumerate自带的索引序号进行映射 insect_category2id[item] = i return insect_category2id 构建xml解析

通过上边的操作,我们就得到了类别映射,后边的的类别名称就可以很方便的解析成id序列号了! 代码具体如下:(所有的重要注释都已经在代码中覆盖了!)

# 传入类别索引字典和xml数据地址进行xml解析 # 返回xml中解析到的所有目标数据 def get_annotation(category2id, data_path): ''' category2id: 类别索引字典 data_path: 数据地址(单个xml的数据的相对地址——1.xml) return records (这是一个list,包含其中返回的字典数据) ''' # data_path: 1.xml => [:-4] = '1' , [-4:] = '.xml' fid = data_path[:-4] # id:既是xml的,通常也是img的 tree = ET.parse(data_path) objs = tree.findall('object') # 返回所有的object对象(标签) img_w = tree.find('size').find('width').text # 通过text属性调用xml指定标签的数据 img_h = tree.find('size').find('height').text # print('Image Width:', img_w, 'px , Image Height:', img_h, 'px') # 预置我们需要从xml中读取的数据格式——这里的bbox采用xywh的数据格式存储 # 根据objs的个数,分配此时解析xml需要多少个bbox gt_bbox = np.zeros((len(objs), 4), dtype=np.float32) # 4:表示bbox的数据: xywh gt_class = np.zeros((len(objs), 1), dtype=np.int32) # 1:对应类别索引 is_difficult = np.zeros((len(objs), 1), dtype=np.int32) # 1:对应是否识别困难 # 预置后数据格式之后,开始遍历objs,依次读取其中的数据,存入到预置的数据格式中 for i, obj in enumerate(objs): # 利用enumerate返回自带索引,来方便多个obj的索引和遍历 # 类别读取 category_name = obj.find('name').text # 获取类别名 category_id = category2id[category_name] # 获取对应的类别索引 gt_class[i] = category_id # 添加识别类别索引 # 识别是否困难 _difficult = int(obj.find('difficult').text) # 获取识别难度 is_difficult[i] = _difficult # 读取目标识别是否困难 # bbox读取 x1 = float(obj.find('bndbox').find('xmin').text) # 将读取的左上点的x数据转换为float数据 y1 = float(obj.find('bndbox').find('ymin').text) x2 = float(obj.find('bndbox').find('xmax').text) # 右下点 y2 = float(obj.find('bndbox').find('ymax').text) # 将读取的bbox数据转换为:xywh的格式存入gt_bbox中 bbox_center_x = (x2 + x1) / 2.0 bbox_center_y = (y2 + y1) / 2.0 bbox_w = (x2 - x1) + 1.0 bbox_h = (y2 - y1) + 1.0 # 写入gt_bbox gt_bbox[i] = [bbox_center_x, bbox_center_y, bbox_w, bbox_h] # 这里等价于将gt_bbox[i,:] = [....] # 将当前xml中的所有obj遍历完后,对数据进行一个汇总 # 具体实践时的数据解析和汇总可以做适当的调整 xml_rcd = { 'image_name': fid+'.png', # 图片名称 'image_id': fid, # 图片id 'difficult': is_difficult, # 数据识别困难情况 'categoty_id': gt_class, # 识别对象的类别情况 'gt_bbox': gt_bbox # 识别对象的bbox情况 } # 返回解析完归总后的xml内容 return xml_rcd 代码测试 # cotegory有7种 INSECT_NAMES = ['Boerner', 'Leconte', 'Linnaeus', 'acuminatus', 'armandi', 'coleoptera', 'linnaeus'] # 生成类别索引字典 category2id = get_insect_name() # 返回解析后的xml内容 xml_rcd = get_annotation(category2id=category2id, data_path='1.xml') # 打印解析出来的内容 for key, data in xml_rcd.items(): # 打印返回的内容 print(key, ':\n', data) # 当前数据的内容

打印结果: 在这里插入图片描述 到这里,xml的基本解析就介绍完了,如果大家感兴趣,可以在此基础上尝试文件列表中多个xml文件的解析。

目标检测相关教程如下:(更新中) 目标检测(一)——边界框总结与代码实现(可完整实现) 目标检测(二)——锚框总结与代码实现(可完整实现) 目标检测(三)——IoU总结与代码实现(可完整实现)



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3