voc的xml转json实现labelme可视化


edited by nrzheng,2022.2.21

VOC数据集简略介绍

1. Pascal VOC(Pascal Visual Object Classes)

VOC数据集是目标检测经常用的一个数据集,从05年到12年都会举办比赛(任务有: Classification 、Detection 、 Segmentation、Person Layout)

2. Annotations

标签文件夹是Annotations,采用xml格式存储(以下以SAR目标检测数据集SSDD为例介绍各字段)

每个xml内容大致如下:

<annotation verified="no">
  <folder>JPEGImages</folder>
  <filename>000001</filename>
  <path>E:\\data\\detection\\SSDD\\JPEGImages\\000001.jpg</path>
  <source>
    <database>Unknown</database>
  </source>
  <size>
    <width>416</width>
    <height>323</height>
    <depth>1</depth>
  </size>
  <segmented>0</segmented>
  <object>
    <name>ship</name>
    <pose>Unspecified</pose>
    <truncated>0</truncated>
    <difficult>0</difficult>
    <bndbox>
      <xmin>208</xmin>
      <ymin>50</ymin>
      <xmax>273</xmax>
      <ymax>151</ymax>
    </bndbox>
  </object>
</annotation>

  • folder:该标签文件对应的图像的文件夹
  • filename:文件名(VOC中放的是加后缀的图像名)
  • path:对应图像的绝对路径(VOC中这部分内容比较详细,source也比较详细)
  • size:图像的尺寸,包括宽、高、通道数
  • segmented:是否用于分割,0为否
  • object:每个object都是一个目标,有的图像中会有多个目标就对应多个object
    • name:目标的类别 / 名称
    • pose:摄像头角度
    • truncated:是否被截断,0表示完整
    • difficult:目标是否难以识别,0表示容易识别
    • bndbox:目标的位置,由于都是正框,所以这里给出的4个值是xmin、ymin、xmax、ymax

3. SSDD数据介绍

3.1. 文件夹结构

SSDD
   ├─Annotations
   ├─JPEGImages
  • Annotations:标签文件,xml格式
  • JPEGImages:图像文件,jpg格式
  • (基本都是这种)

3.2. 标签及图像

Annotations和JPEGImages文件夹的内容如下所示:

在这里插入图片描述

一般在使用之前,要检查以下数据是否准确(个人习惯),但是目标检测的数据集在原图上都没办法看到标签打的情况,因为标签都是独立的一个文件,跟语义分割的标签直接可视化不一样,目标检测的标签都是一些文本。

所以,为了检查标签,需要把标签文件到原图上可视化。这里借助的是工具labelme

labelme介绍

1. labelme

Labelme 是一个图形界面的图像标注软件。其的设计灵感来自于这里 。它是用 Python 语言编写的,图形界面使用的是 Qt(PyQt)。

labelme下载:点击这里,提取码:2o1k

2. labelme使用及界面展示

  • 一般都是直接打开文件夹,把图像文件加载进来
  • 一般都会把file—Save With Image Data关掉。因为这个打开的话,标签文件会保存原图的信息,很长很长,没有必要
  • 这样就可以开始标注了,可以file—Change Output Dir选择标签输出的文件夹
    • 若已有标签,且标签跟原图在一个文件夹,会自动读取标签显示框框
    • 若已有标签,但标签跟原图不在一个文件夹,file—Change Output Dir选到标签所在文件夹,就会自动读取
    • 界面右下角有图像的绝对路径,前面带勾的表示该图像有标签

labelme的界面如下:

在这里插入图片描述

3. labelme标签格式

labelme采用json文件格式存储标签,如下:

{
  "version": "4.5.6",
  "flags": {},
  "shapes": [
    {
      "label": "ship",
      "points": [
        [
          202.66666666666669,
          58.333333333333336
        ],
        [
          229.33333333333331,
          148.33333333333334
        ],
        [
          282.3333333333333,
          134.66666666666666
        ],
        [
          243.66666666666669,
          42.0
        ]
      ],
      "group_id": null,
      "shape_type": "polygon",
      "flags": {}
    }
  ],
  "imagePath": "000001.jpg",
  "imageData": null,
  "imageHeight": 323,
  "imageWidth": 416
}
  • flags:描述你分类的标签有哪些,比如{0, 1}表示二分类,或者多分类也可以{water, road, industry, …}。一般都是空的
  • shapes:里面就是标注的信息,多个的话则shapes里就有多个”{}“
    • label:类别
    • points:构成这个目标的所有点
    • shape_type:形状的类型。polygon代表多边形
    • 因为labelme不局限于画矩形正框,可以有好多点表示一个目标,所以points里面是一个个的点,跟VOC数据用xy的最大最小坐标表示不一样
  • imagePath:图像的路径(我喜欢用绝对路径)
  • imageData:图像的一些信息。上面讲的取消就会输出null,放出来就是一长串字符
  • imageHeight:图像的高
  • imageWidth:图像的宽

VOC的xml转json

前面的介绍知道,要用labelme可视化VOC数据,就要把VOC数据集中的标签(xml格式)转成labelme可识别的标签(json格式)。只要json中的字段对应的上,转换之后就可以打开。转换后可视化如下:

在这里插入图片描述

可以看到,数据集标签没有问题。

代码如下:

"""
    Author:DamonZheng
    Function:xml2json(for labelme)
    Edition:1.0
    Date:2022.2.21
"""

import argparse
import glob
import os
import xml.etree.ElementTree as ET
import json
from tqdm import tqdm

def parse_args():
    """
        参数配置
    """
    parser = argparse.ArgumentParser(description='xml2json')
    parser.add_argument('--raw_label_dir', help='the path of raw label', default=r'E:\data\detection\ship_detection_online\Annotations_new')
    parser.add_argument('--pic_dir', help='the path of picture', default=r'E:\data\detection\ship_detection_online\JPEGImages')
    parser.add_argument('--save_dir', help='the path of new label', default=r'E:\data\detection\ship_detection_online\label_json')
    args = parser.parse_args()
    return args

def read_xml_gtbox_and_label(xml_path):
    """
        读取xml内容
    """
    tree = ET.parse(xml_path)
    root = tree.getroot()
    size = root.find('size')
    width = int(size.find('width').text)
    height = int(size.find('height').text)
    depth = int(size.find('depth').text)
    points = []
    for obj in root.iter('object'):
        cls = obj.find('name').text
        pose = obj.find('pose').text
        xmlbox = obj.find('bndbox')
        xmin = float(xmlbox.find('xmin').text)
        xmax = float(xmlbox.find('xmax').text)
        ymin = float(xmlbox.find('ymin').text)
        ymax = float(xmlbox.find('ymax').text)
        box = [xmin, ymin, xmax, ymax]
        point = [cls, box]
        points.append(point)
    return points, width, height

def main():
    """
        主函数
    """
    args = parse_args()
    labels = glob.glob(args.raw_label_dir + '/*.xml')
    for i, label_abs in tqdm(enumerate(labels), total=len(labels)):
        _, label = os.path.split(label_abs)
        label_name = label.rstrip('.xml')
        img_path = os.path.join(args.pic_dir, label_name + '.jpg')
        points, width, height = read_xml_gtbox_and_label(label_abs)
        json_str = {}
        json_str['version'] = '4.5.6'
        json_str['flags'] = {}
        shapes = []
        for i in range(len(points)):
            shape = {}
            shape['label'] = points[i][0]
            shape['points'] = [[points[i][1][0], points[i][1][1]], 
                                [points[i][1][0], points[i][1][3]], 
                                [points[i][1][2], points[i][1][3]],
                                [points[i][1][2], points[i][1][1]]]
            shape['group_id'] = None
            shape['shape_type'] = 'polygon'
            shape['flags'] = {}
            shapes.append(shape)
        json_str['shapes'] = shapes
        json_str['imagePath'] = img_path
        json_str['imageData'] = None
        json_str['imageHeight'] = height
        json_str['imageWidth'] = width
        with open(os.path.join(args.save_dir, label_name + '.json'), 'w') as f:
            json.dump(json_str, f, indent=2)

if __name__ == '__main__':
    main()
  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
要将XML文件换为LabelMe的JSON格式,可以按照以下步骤进行操作: 1. 安装XML解析库和LabelMe库 首先需要安装`xml.etree.ElementTree`和`labelme`库。可以使用以下命令进行安装: ``` pip install xml pip install labelme ``` 2. 解析XML文件 使用`xml.etree.ElementTree`库来解析XML文件,可以使用以下代码: ```python import xml.etree.ElementTree as ET def parse_xml(xml_file): tree = ET.parse(xml_file) root = tree.getroot() return root ``` 3. 将XML数据换为LabelMe的JSON格式 将XML数据换为LabelMe的JSON格式,可以使用以下代码: ```python import json def xml_to_json(xml_file): root = parse_xml(xml_file) json_data = { "version": "4.5.6", "flags": {}, "shapes": [], "imagePath": "", "imageData": "", "imageHeight": int(root.find("size/height").text), "imageWidth": int(root.find("size/width").text) } for obj in root.findall("object"): label = obj.find("name").text points = [] for pt in obj.find("polygon/pt"): x = int(pt.find("x").text) y = int(pt.find("y").text) points.append([x, y]) json_data["shapes"].append({ "label": label, "points": points, "group_id": None, "shape_type": "polygon", "flags": {} }) return json.dumps(json_data, indent=4) ``` 这个函数将XML数据换为一个Python字典,然后使用`json.dumps()`将其换为JSON格式。在这个函数中,我们首先获取图像的大小,然后遍历每个对象并获取标签和多边形的点。最后,我们将它们添加到JSON数据中。 4. 调用函数并保存JSON文件 调用上面的函数并将结果保存为JSON文件,可以使用以下代码: ```python xml_file = "path/to/xml/file.xml" json_data = xml_to_json(xml_file) with open("path/to/json/file.json", "w") as f: f.write(json_data) ``` 这将把XML文件换为LabelMe的JSON格式,并将结果保存为JSON文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

damonzheng46

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值