两种不同风格的lxml标注文件的解析:pet和Lara_UrbanSeq1_Traffic Light

2024-02-12 04:32

本文主要是介绍两种不同风格的lxml标注文件的解析:pet和Lara_UrbanSeq1_Traffic Light,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. pet数据集标注样式

以Abyssinian_12.xml为例,文件内容如下:

<annotation><folder>OXIIIT</folder><filename>Abyssinian_12.jpg</filename><source><database>OXFORD-IIIT Pet Dataset</database><annotation>OXIIIT</annotation><image>flickr</image></source><size><width>335</width><height>500</height><depth>3</depth></size><segmented>0</segmented><object><name>cat</name><pose>Frontal</pose><truncated>0</truncated><occluded>0</occluded><bndbox><xmin>94</xmin><ymin>83</ymin><xmax>211</xmax><ymax>190</ymax></bndbox><difficult>0</difficult></object>
</annotation>

分析可知,其节点全部为tag:text形式,每个tag不包含attrib。因此,参照Object Detection API官方,采用以下方式来进行递归读取,返回一个包含多层级字典结构的数据。

import numpy as np
import PIL.Image
import tensorflow as tf
from lxml import etreefrom object_detection.dataset_tools import tf_record_creation_util
from object_detection.utils import dataset_util
from object_detection.utils import label_map_utilxml_path = "./Annotations/Abyssinian_12.xml"
# xml_path = "./Annotations/Lara_test.xml"with tf.gfile.GFile(xml_path, 'r') as fid:xml_str = fid.read()xml = etree.fromstring(xml_str)
#     xml = etree.fromstring(xml_str.encode('utf-8'))data = dataset_util.recursive_parse_xml_to_dict(xml)['annotation']
#     data = dataset_util.recursive_parse_xml_to_dict(xml)print(data)
#     for item in data:
#         print(type(item))

其中调用的函数recursive_parse_xml_to_dict(xml)如下:

def recursive_parse_xml_to_dict(xml):"""Recursively parses XML contents to python dict.We assume that `object` tags are the only ones that can appearmultiple times at the same level of a tree.Args:xml: xml tree obtained by parsing XML file contents using lxml.etreeReturns:Python dictionary holding XML contents."""if not xml:return {xml.tag: xml.text}result = {}for child in xml:child_result = recursive_parse_xml_to_dict(child)if child.tag != 'object':result[child.tag] = child_result[child.tag]else:if child.tag not in result:result[child.tag] = []result[child.tag].append(child_result[child.tag])return {xml.tag: result}

2. Lara标注样式

Lara交通标志数据集的标注文件将所有的图片文件信息整合在一个文件中,截取一段如下:

<?xml version="1.0" encoding="UTF-8"?>
<dataset name="Lara_UrbanSeq1" version="0.5" comments="Public database: http://www.lara.prd.fr/benchmarks/trafficlightsrecognition"><frame number="6695" sec="487" ms="829"><objectlist><object id="18"><orientation>90</orientation><box h="39" w="18" xc="294" yc="34"/><appearance>appear</appearance><hypothesislist><hypothesis evaluation="1.0" id="1" prev="1.0"><type evaluation="1.0">Traffic Light</type><subtype evaluation="1.0">go</subtype></hypothesis></hypothesislist></object><object id="19"><orientation>90</orientation><box h="15" w="6" xc="518" yc="123"/><appearance>appear</appearance><hypothesislist><hypothesis evaluation="1.0" id="1" prev="1.0"><type evaluation="1.0">Traffic Light</type><subtype evaluation="1.0">go</subtype></hypothesis></hypothesislist></object><object id="20"><orientation>90</orientation><box h="15" w="6" xc="382" yc="122"/><appearance>appear</appearance><hypothesislist><hypothesis evaluation="1.0" id="1" prev="1.0"><type evaluation="1.0">Traffic Light</type><subtype evaluation="1.0">go</subtype></hypothesis></hypothesislist></object></objectlist><grouplist></grouplist></frame>
</dataset>

可见其主要信息都包含在tag:attrib中,是难以用递归函数来实现解析的。
对该文件进行单独测试如下:

# 测试解析xml文件
# examples_path = os.path.join(annotations_dir, 'trainval.txt')
# examples_list = dataset_util.read_examples_list(examples_path)
# xml_path = "./Annotations/Lara_UrbanSeq1_GroundTruth_cvml.xml"
# tree = ET.parse(xml_path)
# root = tree.getroot()
# print(root.tag)
# print(root.attrib)
# print(root[11178].tag)
# print(root[11178].attrib)
# print(root[11178][0][0].tag)
# print(root[11178][0][0].attrib)
# for frame in root.findall("./frame")
# for obj in root[11178][0][0]:
#     print(obj.attrib)
#     print(obj.tag)

主要实现代码如下:

# 从xml文件解析出数据,以list形式返回。每个list的item都是包含相关信息的一个dict
def get_data_list(xml_path, label_map_dict):"""Function: parse xml to a list of image data, every item contain a dict of image name, size, and a list of objects.Args:xml_path: the path to the xml fileReturns:data_list: a list of data, every data is a dict contain keys.{   'filename': 'frame_006630.jpg', 'size':    {'width': 640, 'height': 480}, 'object':  [ {'bndbox': {'xmin': 368, 'xmax': 378, 'ymin': 94, 'ymax': 116}}, {'bndbox': {'xmin': 563, 'xmax': 571, 'ymin': 103, 'ymax': 123}}]}"""tree = ET.parse(xml_path)root = tree.getroot()data_list = []for frame in root.findall('./frame'):frame_number = int(frame.get("number"))img_name = "frame_{0:06d}.jpg".format(frame_number) # 得到第一个字段,文件名data = dict()data['filename']=img_nameimg_size = dict()img_size['width']=640img_size['height']=480data['size']=img_sizeobject_list=[]data['object']=object_listfor obj in frame.findall('./objectlist/object'): # 得到该帧里的每个objectobject = dict()# 这里待验证。暂时仍用读到的字符串,而没有转换为数字class_name = obj.find('./hypothesislist/hypothesis/subtype').text
#             classes_text.append(class_name.encode('utf-8'))
#             classes.append(label_map_dict[class_name])object['class_text'] = class_nameobject['class_id'] = label_map_dict[class_name]obj_h = int(obj.find('box').get("h"))    obj_w = int(obj.find('box').get("w"))obj_xc = int(obj.find('box').get("xc"))obj_yc = int(obj.find('box').get("yc"))xmin = obj_xc-int(obj_w//2)if xmin<0:xmin=0xmax = obj_xc+int(obj_w//2)ymin = obj_yc-int(obj_h//2)if ymin<0:ymin=0ymax = obj_yc+int(obj_h//2)bndbox = dict()            bndbox['xmin'] = xminbndbox['xmax'] = xmaxbndbox['ymin'] = yminbndbox['ymax'] = ymaxobject['bndbox'] = bndboxobject_list.append(object)data_list.append(data)return data_list

3. 主要对比

前者使用lxml.etree,后者使用xml.etree.ElementTree。解析过程不同。

这篇关于两种不同风格的lxml标注文件的解析:pet和Lara_UrbanSeq1_Traffic Light的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/701668

相关文章

idea设置快捷键风格方式

《idea设置快捷键风格方式》在IntelliJIDEA中设置快捷键风格,打开IDEA,进入设置页面,选择Keymap,从Keymaps下拉列表中选择或复制想要的快捷键风格,点击Apply和OK即可使... 目录idea设www.chinasem.cn置快捷键风格按照以下步骤进行总结idea设置快捷键pyth

MySQL字符串转数值的方法全解析

《MySQL字符串转数值的方法全解析》在MySQL开发中,字符串与数值的转换是高频操作,本文从隐式转换原理、显式转换方法、典型场景案例、风险防控四个维度系统梳理,助您精准掌握这一核心技能,需要的朋友可... 目录一、隐式转换:自动但需警惕的&ld编程quo;双刃剑”二、显式转换:三大核心方法详解三、典型场景

MyBatis中的两种参数传递类型详解(示例代码)

《MyBatis中的两种参数传递类型详解(示例代码)》文章介绍了MyBatis中传递多个参数的两种方式,使用Map和使用@Param注解或封装POJO,Map方式适用于动态、不固定的参数,但可读性和安... 目录✅ android方式一:使用Map<String, Object>✅ 方式二:使用@Param

python项目打包成docker容器镜像的两种方法实现

《python项目打包成docker容器镜像的两种方法实现》本文介绍两种将Python项目打包为Docker镜像的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录简单版:(一次成功,后续下载对应的软件依赖)第一步:肯定是构建dockerfile,如下:第二步

SQL 注入攻击(SQL Injection)原理、利用方式与防御策略深度解析

《SQL注入攻击(SQLInjection)原理、利用方式与防御策略深度解析》本文将从SQL注入的基本原理、攻击方式、常见利用手法,到企业级防御方案进行全面讲解,以帮助开发者和安全人员更系统地理解... 目录一、前言二、SQL 注入攻击的基本概念三、SQL 注入常见类型分析1. 基于错误回显的注入(Erro

C++ 多态性实战之何时使用 virtual 和 override的问题解析

《C++多态性实战之何时使用virtual和override的问题解析》在面向对象编程中,多态是一个核心概念,很多开发者在遇到override编译错误时,不清楚是否需要将基类函数声明为virt... 目录C++ 多态性实战:何时使用 virtual 和 override?引言问题场景判断是否需要多态的三个关

MySQL集群高可用架构的两种使用小结

《MySQL集群高可用架构的两种使用小结》本文介绍了MySQL的两种高可用解决方案:组复制(MGR)和MasterHighAvailability(MHA),文中通过示例代码介绍的非常详细,对大家的学... 目录一、mysql高可用之组复制(MGR)1.1 组复制核心特性与优势1.2 组复制架构原理1.3

Springboot主配置文件解析

《Springboot主配置文件解析》SpringBoot主配置文件application.yml支持多种核心值类型,包括字符串、数字、布尔值等,文章详细介绍了Profile环境配置和加载位置,本文... 目录Profile环境配置配置文件加载位置Springboot主配置文件 application.ym

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node