Python解析VOC数据标签文件

Posted 修炼之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python解析VOC数据标签文件相关的知识,希望对你有一定的参考价值。

导读

在目标检测数据集中我们经常会使用到VOC格式的数据,这篇文章就向大家介绍一下如何来解析xml标签文件的数据

xml数据

<annotation>
  <folder>/root/datasets</folder>
  <filename>/root/datasets/example/example.jpg</filename>
  <source>
    <database>Unknown</database>
    <annotation>Unknown</annotation>
    <image>Unknown</image>
  </source>
  <size>
    <width>1080</width>
    <height>1440</height>
    <depth></depth>
  </size>
  <segmented>0</segmented>
  <object>
    <name>1</name>
    <occluded>0</occluded>
    <bndbox>
      <xmin>767.78</xmin>
      <ymin>65.87</ymin>
      <xmax>792.08</xmax>
      <ymax>102.33</ymax>
    </bndbox>
  </object>
  <object>
    <name>2</name>
    <occluded>0</occluded>
    <bndbox>
      <xmin>378.89</xmin>
      <ymin>546.77</ymin>
      <xmax>403.19</xmax>
      <ymax>583.23</ymax>
    </bndbox>
  </object>
</annotation>

解析xml数据

python的xml库提供了几种不同的方法来解析xml文件,下面我们来介绍如何通过ElementTreeminidom来解析xml文件

使用ElementTree解析xml数据

通过ElementTree解析xml数据主要分为下面几个步骤:

  1. 使用getroot方法来获取xml的根节点信息
  2. 使用find方法来找到不需要遍历节点的信息
  3. 通过iter来编译包含多个相同节点的信息
import xml.etree.ElementTree as ET

def parse_xml(xml_path):
    #读取xml文件
    rf = open(xml_path,"r")
    #开始解析xml文件
    tree = ET.parse(rf)
    #获取根节点信息
    root = tree.getroot()

    #获取图片的路径
    img_path = root.find("filename").text
    #获取图片的size节点的信息
    size = root.find("size")
    #获取图片的宽
    img_width = size.find("width").text
    #获取图片的高
    img_height = size.find("height").text

    #解析图片的box信息
    #遍历object节点的信息
    label_infos = []
    for object in root.iter("object"):
        #获取类别的名称
        name = object.find("name").text
        #获取标签的识别难度
        occluded = object.find("occluded").text
        #获取标签的box信息
        bndbox = object.find("bndbox")
        xmin = float(bndbox.find('xmin').text)
        xmax = float(bndbox.find('xmax').text)
        ymin = float(bndbox.find('ymin').text)
        ymax = float(bndbox.find('ymax').text)
        box = (xmin,xmax,ymin,ymax)
        label_infos.append((name,occluded,box))
    return label_infos,img_width,img_height

使用minidom来解析xml文件

使用minidom来解析xml相对于ElementTree来说要稍微复杂一点,minidom主要通过getElementsByTagName函数来寻找节点,然后再通过childNodes来逐步解析xml文件,我将minidom解析xml文件以及封装成了三个函数:

  1. get_all_node获取节点下面所有的子节点
  2. get_node_value获取节点的值
  3. get_node_name获取节点的名称
from xml.dom import minidom

def parse_xml_by_minidom(xml_path):

    def get_node_name(node):
        """获取节点的名字
        :param node:
        :return:
        """
        return node.nodeName


    def get_node_value(node):
        """获取node的值
        :param node:
        :return:
        """
        child_nodes = node.childNodes
        return child_nodes[0].nodeValue

    def get_all_node(node,node_list):
        """获取所有的节点
        :param node:
        :param node_list:
        :return:
        """
        for child_node in node.childNodes:
            if isinstance(child_node,minidom.Element):
                child_nodes = child_node.childNodes
                if len(child_nodes) == 1:
                    node_list.append(child_node)
                else:
                    get_all_node(child_node,node_list)


    def get_all_child_value(node):
        """获取节点所有子节点信息
        :param node:
        :return:
        """
        node_list = []
        get_all_node(node,node_list)
        node_info = 
        for node in node_list:
            node_name = get_node_name(node)
            node_value = get_node_value(node)
            if node_value is not None:
                node_info[node_name] = node_value
        return node_info


    doc = minidom.parse(xml_path)
    #获取跟节点
    root = doc.documentElement
    #获取图片的路径
    img_path_node = root.getElementsByTagName("filename")[0]
    #获取节点的名称
    node_name = get_node_name(img_path_node)
    #获取节点的值
    img_path = get_node_value(img_path_node)
    size_node_list = root.getElementsByTagName("size")
    size_info = get_all_child_value(size_node_list[0])
    #获取图片的宽和高
    img_width = size_info["width"]
    img_height = size_info["height"]
    #获取标签信息
    box_info_list = []
    object_node_list = root.getElementsByTagName("object")
    for object_node in object_node_list[:1]:
        box_node_info = get_all_child_value(object_node)
        box_info_list.append(box_node_info)
    return box_info_list,img_width,img_height

以上是关于Python解析VOC数据标签文件的主要内容,如果未能解决你的问题,请参考以下文章

Python解析VOC数据标签文件

python [xml文件到voc的csv文件]将voc标签转换为xml格式为csv格式#python #csv #xml

labelimg标注的VOC格式标签xml文件和yolo格式标签txt文件相互转换

YOLO-Darknet实战:VOC2007标签格式转换成Darknet标签格式

YOLO-Darknet实战:VOC2007标签格式转换成Darknet标签格式

SSD中VOC数据的边界框标签