目标检测篇:如何根据xml标注文件生成类别classes的json文件

发布时间:2024年01月04日

1. 介绍

之前在做目标检测任务的时候,发现很多的数据集仅有数据(只有图片+标注的xml文件),没有关于类别的json文件,为了以后方便使用,这里记录一下

一般来说,yolo标注的数据集,只有第一个是数字类别,要是没有classes对应的类别,只能根据图片一个个输入。

对于xml解释性标签文件,标注的时候,object下面的name就是目标检测框的分类,所以这里只有xml生成类别json文件的代码

2. 实现代码

代码实现简单,仅有50行,这里简单介绍

这里root传入的是数据集的xml目录,因为训练集包含本检测任务的所有分类,这里传入的是目录

if __name__ == "__main__":
    root = './my_xml_dataset/train/annotations'          # 数据集的 xml 目录
    xml2json(root)

下面读取xml文件的内容,这里的data以及将单个xml文件全部解析出来

  • open里面的encoding和errors参数是因为本实验的xml包含中文字符,这样可以防止报错,正常的话不需要这两个参数,如果xml编码不一样,根据报错信息,百度一下传入不同编码就行了
  • parse_xml_to_dict? 为自定义函数,后面会贴所有代码,这里只需要知道利用递归将xml文件解析成字典文件即可,看下面的data打印信息

接着开始读取单个xml的所有目标类别,如下

classes需要去除重复的目标,生成单个的classes文件

最好生成json文件即可

可以看出,测试数据的目标共有10347个

生成的json文件如下:

3. 完整代码

如下:

import os
from tqdm import tqdm
from lxml import etree
import json


# 读取 xml 文件信息,并返回字典形式
def parse_xml_to_dict(xml):
    if len(xml) == 0:  # 遍历到底层,直接返回 tag对应的信息
        return {xml.tag: xml.text}

    result = {}
    for child in xml:
        child_result = parse_xml_to_dict(child)  # 递归遍历标签信息
        if child.tag != 'object':
            result[child.tag] = child_result[child.tag]
        else:
            if child.tag not in result:  # 因为object可能有多个,所以需要放入列表里
                result[child.tag] = []
            result[child.tag].append(child_result[child.tag])
    return {xml.tag: result}


# 提取xml中name保留为json文件
def xml2json(data):
    xml_path = [os.path.join(data, i) for i in os.listdir(data)]
    classes = []      # 目标类别
    num_object = 0
    for xml_file in tqdm(xml_path, desc="loading..."):
        with open(xml_file,encoding='gb18030',errors='ignore') as fid:      # 防止出现非法字符报错
            xml_str = fid.read()
        xml = etree.fromstring(xml_str)
        data = parse_xml_to_dict(xml)["annotation"]  # 读取xml文件信息
        for j in data['object']:        # 获取单个xml文件的目标信息
            ob = j['name']
            num_object +=1
            if ob not in classes:
                classes.append(ob)
    print(num_object)
    # 生成json文件
    labels = {}
    for index,object in enumerate(classes):
        labels[index] = object
    labels = json.dumps(labels,indent=4)
    with open('class_indices.json','w') as f:
        f.write(labels)


if __name__ == "__main__":
    root = './my_xml_dataset/train/annotations'          # 数据集的 xml 目录
    xml2json(root)

下载地址:关于目标检测:如何根据XML标签文件生成检测类别的json字典文件,包含数据集、测试代码以及生成好的json文件

文章来源:https://blog.csdn.net/qq_44886601/article/details/135393350
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。