【数据集转换】VOC数据集转COCO数据集·代码实现+操作步骤

您所在的位置:网站首页 coco与cocoiris 【数据集转换】VOC数据集转COCO数据集·代码实现+操作步骤

【数据集转换】VOC数据集转COCO数据集·代码实现+操作步骤

2024-03-15 02:51| 来源: 网络整理| 查看: 265

在自己的数据集上实验时,往往需要将VOC数据集转化为coco数据集,因为这种需求所以才记录这篇文章,代码出处未知,感谢开源。

在远程服务器上测试目标检测算法需要用到测试集,最常用的是coco2014/2017和voc07/12数据集。

coco数据集的地址为http://cocodataset.org/#download voc和coco的镜像为https://pjreddie.com/projects/pascal-voc-dataset-mirror/

一、数据集格式对比 1.1 VOC数据集 VOC_ROOT #根目录 ├── JPEGImages # 存放源图,(当然图片并不一定要是**.jpg格式的,只是规定文件夹名字叫JPEGImages**); │ ├── aaaa.jpg │ ├── bbbb.jpg │ └── cccc.jpg ├── Annotations # 存放xml文件,VOC的标注是xml格式,与JPEGImages中的图片一一对应 │ ├── aaaa.xml │ ├── bbbb.xml │ └── cccc.xml └── ImageSets └── Main ├── train.txt # txt文件中每一行包含一个图片的名称 └── val.txt 1.2 COCO数据集 COCO_ROOT #根目录 ├── annotations # 存放json格式的标注 │ ├── instances_train2017.json │ └── instances_val2017.json └── train2017 # 存放图片文件 │ ├── 000000000001.jpg │ ├── 000000000002.jpg │ └── 000000000003.jpg └── val2017 ├── 000000000004.jpg └── 000000000005.jpg 1.2.3 json标注格式

与VOC一个文件一个xml标注不同,COCO所有的目标框标注都是放在一个json文件中的。 这个json文件解析出来是一个字典,格式如下:

{ "info": info, "images": [image], "annotations": [annotation], "categories": [categories], "licenses": [license], } 二、转换步骤 2.1 程序总体目录

 2.2  标签文件转换代码实现(xml文件转json格式)VOC_To_CoCo_01.py

这里需要运行三次,因为train.txt val.txt test.txt是三个文件,具体看注释

import sys import os import json import xml.etree.ElementTree as ET START_BOUNDING_BOX_ID = 0 PRE_DEFINE_CATEGORIES = {"air-hole": 1, "broken-arc": 2, "hollow-bead": 3, "overlap": 4, "unfused": 5, "bite-edge": 6, "crack": 7, "slag-inclusion": 8} # 修改的地方,修改为自己的类别 # 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 filename except: raise NotImplementedError('Filename %s is supposed to be an integer.' % (filename)) # xml_list为xml文件存放的txt文件名 xml_dir为真实xml的存放路径 json_file为存放的json路径 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() line = line + ".xml" 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__': # xml_list为xml文件存放的txt文件名 xml_dir为真实xml的存放路径 json_file为存放的json路径 # xml_list = './data/VOCdevkit/ImageSets/Main/test.txt' # xml_list = './data/VOCdevkit/ImageSets/Main/train.txt' xml_list = './data/VOCdevkit/ImageSets/Main/val.txt' xml_dir = './data/VOCdevkit/Annotations' # json_dir = './data/COCO/annotations/test.json' # 注意!!!这里test.json先要自己创建,不然 # json_dir = './data/COCO/annotations/train.json' # 注意!!!这里test.json先要自己创建,不然 json_dir = './data/COCO/annotations/val.json' # 注意!!!这里test.json先要自己创建,不然 #程序回报权限不足 convert(xml_list, xml_dir, json_dir) 2.3 数据集图像文件copy代码实现(复制图片数据集到coco中)VOC_To_CoCo_02.py # VOC_To_CoCo_02.py import os import shutil images_file_path = './VOCdevkit/JPEGImages/' split_data_file_path = './VOCdevkit/ImageSets/Main/' new_images_file_path = './output/' if not os.path.exists(new_images_file_path + 'train'): os.makedirs(new_images_file_path + 'train') if not os.path.exists(new_images_file_path + 'val'): os.makedirs(new_images_file_path + 'val') if not os.path.exists(new_images_file_path + 'test'): os.makedirs(new_images_file_path + 'test') dst_train_Image = new_images_file_path + 'train/' dst_val_Image = new_images_file_path + 'val/' dst_test_Image = new_images_file_path + 'test/' total_txt = os.listdir(split_data_file_path) for i in total_txt: name = i[:-4] if name == 'train': txt_file = open(split_data_file_path + i, 'r') for line in txt_file: line = line.strip('\n') line = line.strip('\r') srcImage = images_file_path + line + '.jpg' dstImage = dst_train_Image + line + '.jpg' shutil.copyfile(srcImage, dstImage) txt_file.close() elif name == 'val': txt_file = open(split_data_file_path + i, 'r') for line in txt_file: line = line.strip('\n') line = line.strip('\r') srcImage = images_file_path + line + '.jpg' dstImage = dst_val_Image + line + '.jpg' shutil.copyfile(srcImage, dstImage) txt_file.close() elif name == 'test': txt_file = open(split_data_file_path + i, 'r') for line in txt_file: line = line.strip('\n') line = line.strip('\r') srcImage = images_file_path + line + '.jpg' dstImage = dst_test_Image + line + '.jpg' shutil.copyfile(srcImage, dstImage) txt_file.close() else: print("Error, Please check the file name of folder") 三、效果展示



【本文地址】


今日新闻


推荐新闻


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