VOC数据集和COCO数据集直接的相互转换

您所在的位置:网站首页 格式转换失败原因有哪些 VOC数据集和COCO数据集直接的相互转换

VOC数据集和COCO数据集直接的相互转换

#VOC数据集和COCO数据集直接的相互转换| 来源: 网络整理| 查看: 265

VOC数据集(xml格式)和COCO数据集(json格式)的相互转换

我们先来看看voc和coco数据集的目录结构: 以VOC2012数据集为例,下载下来有如下五个文件夹: 在这里插入图片描述 Annotations文件夹是存放图片对应的xml文件,比如“2007_000027.xml"存放的是图片2007_000027.jpg对应的信息,用记事本打开可以看到,这是xml格式的数据。 ImageSets文件夹里存放了官方为我们划分好的训练集和验证集的txt文件。我们主要使用“ImageSets/Main/"文件夹下的train.txt和val.txt文件,train.txt文件存放了官方划分的训练集的图片名称,val.txt文件存放了验证集图片的名称。 还有一个需要关注的文件夹就是JEPGImages,里面存放了对应图片名称的原始图片。剩下的两个文件夹我们就不需要特别关注了。

接下来我们来看看voc数据集的xml文件里面都有哪些信息。

文件夹目录 图片名.jpg path_to\at002eg001.jpg Unknown 550 518 3 0 Apple Unspecified 0 0 292 218 410 331 ...

可以看到一个xml文件包含如下信息:

folder: 文件夹filename:文件名path:路径source:来源size:图片大小segmented:图像分割会用到,本文仅以目标检测(bounding box为例进行介绍)object:一个xml文件可以有多个object,每个object表示一个box,每个box有如下信息组成:name:改box框出来的object属于哪一类,例如Applebndbox:给出左上角和右下角的坐标truncated:是否被截difficult:是否为检测困难物体

不同于VOC,一张图片对应一个xml文件,coco是直接将所有图片以及对应的box信息写在了一个json文件里。通常整个coco目录长这样:

coco |______annotations # 存放标注信息 | |__train.json | |__val.json | |__test.json |______trainset # 存放训练集图像 |______valset # 存放验证集图像 |______testset # 存放测试集图像

一个标准的json文件包含如下信息:

{ "info" : info, "licenses" : [license], "images" : [image], "annotations" : [annataton], "categories" : [category] }

通过上面的json整体结构可以看出,info这个key对应的值的类型是一个字典;licenses、images、annotations和categories这四个key对应的值的类型都是一个列表,列表当中存储的数据类型依旧是字典。 我们可以通过len(List)的方式得到images、annotations、categories这三个列表的长度,也就得到了以下内容。

(1)images字段列表元素的长度 = 划入训练集(或者测试集)的图片的数量; (2)annotations字段列表元素的数量 = 训练集(或者测试集)中bounding box的数量; (3)categories字段列表元素的数量 = 类别的数量

接下来我们看每个key对应的内容:

(1)info info{ "year" : int, # 年份 "version" : str, # 版本 "description" : str, # 详细描述信息 "contributor" : str, # 作者 "url" : str, # 协议链接 "date_created" : datetime, # 生成日期 } (2)images "images": [ {"id": 0, # int 图像id,可从0开始 "file_name": "0.jpg", # str 文件名 "width": 512, # int 图像的宽 "height": 512, # int 图像的高 "date_captured": "2020-04-14 01:45:07.508146", # datatime 获取日期 "license": 1, # int 遵循哪个协议 "coco_url": "", # str coco图片链接url "flickr_url": "" # str flick图片链接url }] (3)licenses "licenses": [ { "id": 1, # int 协议id号 在images中遵循的license即1 "name": null, # str 协议名 "url": null # str 协议链接 }] (4)annotations "annotations": [ { "id": 0, # int 图片中每个被标记物体的id编号 "image_id": 0, # int 该物体所在图片的编号 "category_id": 2, # int 被标记物体的类别id编号 "iscrowd": 0, # 0 or 1 目标是否被遮盖,默认为0 "area": 4095.9999999999986, # float 被检测物体的面积(64 * 64 = 4096) "bbox": [200.0, 416.0, 64.0, 64.0], # [x, y, width, height] 目标检测框的坐标信息 "segmentation": [[200.0, 416.0, 264.0, 416.0, 264.0, 480.0, 200.0, 480.0]] }]

"bbox"里[x, y, width, height]x, y代表的是物体的左上角的x, y的坐标值。

"segmentation"里[x1, y1, x2, y2, x3, y3, x4, y4]是以左上角坐标为起始,顺时针依次选取的另外三个坐标点。及[左上x, 左上y, 右上x,右上y,右下x,右下y,左下x,左下y]。

(5)categories "categories":[ { "id": 1, # int 类别id编号 "name": "rectangle", # str 类别名字 "supercategory": "None" # str 类别所属的大类,如卡车和轿车都属于机动车这个class }, { "id": 2, "name": "circle", "supercategory": "None" } ] 一、将voc数据集的xml转化为coco数据集的json格式

GitHub开源项目地址

开始转换前,得先将要转化的所有.xml文件名保存在xml_list.txt列表中。如果是自己制作的voc数据集,在输入标签名的时候记得不要把类别名name打错了。

# create_xml_list.py import os xml_list = os.listdir('C:/Users/user/Desktop/train') with open('C:/Users/user/Desktop/xml_list.txt','a') as f: for i in xml_list: if i[-3:]=='xml': f.write(str(i)+'\n')

执行python voc2coco.py xml_list.txt的文件路径 .xml文件的真实存放路径 转化后的.json存放路径即可将xml转化为一个.json文件。

# voc2coco.py # pip install lxml import sys import os import json import xml.etree.ElementTree as ET START_BOUNDING_BOX_ID = 1 PRE_DEFINE_CATEGORIES = {} # If necessary, pre-define category and its id # PRE_DEFINE_CATEGORIES = {"aeroplane": 1, "bicycle": 2, "bird": 3, "boat": 4, # "bottle":5, "bus": 6, "car": 7, "cat": 8, "chair": 9, # "cow": 10, "diningtable": 11, "dog": 12, "horse": 13, # "motorbike": 14, "person": 15, "pottedplant": 16, # "sheep": 17, "sofa": 18, "train": 19, "tvmonitor": 20} def get(root, name): vars = root.findall(name) return vars def get_and_check(root, name, length): vars = root.findall(name) if len(vars) == 0: raise NotImplementedError('Can not find %s in %s.'%(name, root.tag)) if length > 0 and len(vars) != length: raise NotImplementedError('The size of %s is supposed to be %d, but is %d.'%(name, length, len(vars))) if length == 1: vars = vars[0] return vars def get_filename_as_int(filename): try: filename = os.path.splitext(filename)[0] return int(filename) except: raise NotImplementedError('Filename %s is supposed to be an integer.'%(filename)) def convert(xml_list, xml_dir, json_file): list_fp = open(xml_list, 'r') json_dict = {"images":[], "type": "instances", "annotations": [], "categories": []} categories = PRE_DEFINE_CATEGORIES bnd_id = START_BOUNDING_BOX_ID for line in list_fp: line = line.strip() print("Processing %s"%(line)) xml_f = os.path.join(xml_dir, line) tree = ET.parse(xml_f) root = tree.getroot() path = get(root, 'path') if len(path) == 1: filename = os.path.basename(path[0].text) elif len(path) == 0: filename = get_and_check(root, 'filename', 1).text else: raise NotImplementedError('%d paths found in %s'%(len(path), line)) ## The filename must be a number image_id = get_filename_as_int(filename) size = get_and_check(root, 'size', 1) width = int(get_and_check(size, 'width', 1).text) height = int(get_and_check(size, 'height', 1).text) image = {'file_name': filename, 'height': height, 'width': width, 'id':image_id} json_dict['images'].append(image) ## Cruuently we do not support segmentation # segmented = get_and_check(root, 'segmented', 1).text # assert segmented == '0' for obj in get(root, 'object'): category = get_and_check(obj, 'name', 1).text if category not in categories: new_id = len(categories) categories[category] = new_id category_id = categories[category] bndbox = get_and_check(obj, 'bndbox', 1) xmin = int(get_and_check(bndbox, 'xmin', 1).text) - 1 ymin = int(get_and_check(bndbox, 'ymin', 1).text) - 1 xmax = int(get_and_check(bndbox, 'xmax', 1).text) ymax = int(get_and_check(bndbox, 'ymax', 1).text) assert(xmax > xmin) assert(ymax > ymin) o_width = abs(xmax - xmin) o_height = abs(ymax - ymin) ann = {'area': o_width*o_height, 'iscrowd': 0, 'image_id': image_id, 'bbox':[xmin, ymin, o_width, o_height], 'category_id': category_id, 'id': bnd_id, 'ignore': 0, 'segmentation': []} json_dict['annotations'].append(ann) bnd_id = bnd_id + 1 for cate, cid in categories.items(): cat = {'supercategory': 'none', 'id': cid, 'name': cate} json_dict['categories'].append(cat) json_fp = open(json_file, 'w') json_str = json.dumps(json_dict) json_fp.write(json_str) json_fp.close() list_fp.close() if __name__ == '__main__': if len(sys.argv)


【本文地址】


今日新闻


推荐新闻


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