VOC格式转COCO之目标检测

文章目录

  • 1、获取标注文件及label名与ID对应关系
    • 1.1 获取label2id及标注xml路径
  • 2 xml格式转coco

深度学习目标检测所用主流的格式是coco ,VOC,可还可以算上yolo,但是前两种更主要,yolo可以通过代码快速转换存到txt文件中。所以前两种的互相转换相当重要,之前的文单中已经写了coco转voc,这里简单写写voc转coco.对于自己的数据集要灵活的去处理,只要改一小部分代码即可写现。

mydata
├── Annotations
├── JPEGImages
├── label_list.txt
├── train.txt
└── valid.txt

2 directories, 3 files

以上是数据处理完成后的目标检测数据信的结构,label_list.txt中存放按首字母排序的类字符串,一个类一行;划分训练和验证集的train.txt和valid.txt则是存放图片的图片咱径和标注文件路径,大概是这样:
mydata/JPEGImages/1.jpg mydata/Annotations/1.xml 一张片一行。

1、获取标注文件及label名与ID对应关系

以上边我们的xml数据集为例(其它也可以,反正是一个文件夹放图片,一个文件夹放标注,还是一个是标签文件.本文整个全流程只提供一个小的参考,由于自定义数据格式多样,只要接照流程能获取相应的要素就可以。

1.1 获取label2id及标注xml路径

import glob

ann_path = "mydata/Annotations" # 相对路径或绝对路径都可以只要能该问到就可以
labels_path = "mydata/label_list.txt"
def voc_get_label_anno(ann_path, labels_path):
    with open(labels_path, 'r') as f:
        labels_str = f.read().split()
    labels_ids = list(range(1, len(labels_str) + 1))
    with open(ann_path,'r') as f:
        all_lines = f.readlines()
    rootdir = os.path.dirname(ann_path)
    ann_paths = [os.path.join(rootdir,i.strip().split(' ')[-1][2:]) for i in all_lines]

    return dict(zip(labels_str, labels_ids)), ann_paths
label2id, ann_paths = voc_get_label_anno("/data/VOCdevkit/train.txt","/data/VOCdevkit/label_list.txt")
label2id
{'screen': 1}
ann_paths[:3]
['/data/VOCdevkit/d1/Annotations/微信截图_20220317104310.xml',
 '/data/VOCdevkit/d1/Annotations/微信截图_20220228173530.xml',
 '/data/VOCdevkit/d1/Annotations/微信截图_20220313163312.xml']

2 xml格式转coco

from tqdm import tqdm
import xml.etree.ElementTree as ET
import json
def voc_xmls_to_cocojson(annotation_paths, label2id, output_dir, output_file):
    output_json_dict = {
        "images": [],
        "type": "instances",
        "annotations": [],
        "categories": []
    }
    bnd_id = 1  # bounding box start id
    im_id = 0
    print('Start converting !')
    for a_path in tqdm(annotation_paths):
        # Read annotation xml
        ann_tree = ET.parse(a_path)
        ann_root = ann_tree.getroot()

        filename = ann_root.findtext('filename')
        assert filename is not None
        img_name = os.path.basename(filename)

        size = ann_root.find('size')
        width = float(size.findtext('width'))
        height = float(size.findtext('height'))

        img_info = {
            'file_name': filename,
            'height': height,
            'width': width,
            'id': im_id
    }
        output_json_dict['images'].append(img_info)

        for obj in ann_root.findall('object'):
            label = obj.findtext('name')
            assert label in label2id, "label is not in label2id."
            category_id = label2id[label]
            bndbox = obj.find('bndbox')
            xmin = float(bndbox.findtext('xmin'))
            ymin = float(bndbox.findtext('ymin'))
            xmax = float(bndbox.findtext('xmax'))
            ymax = float(bndbox.findtext('ymax'))
            assert xmax > xmin and ymax > ymin, "Box size error."
            o_width = xmax - xmin
            o_height = ymax - ymin
            anno = {
                'area': o_width * o_height,
                'iscrowd': 0,
                'bbox': [xmin, ymin, o_width, o_height],
                'category_id': category_id,
                'ignore': 0,
            }
            anno.update({'image_id': im_id, 'id': bnd_id})
            output_json_dict['annotations'].append(anno)
            bnd_id = bnd_id + 1
        im_id += 1

    for label, label_id in label2id.items():
        category_info = {'supercategory': 'none', 'id': label_id, 'name': label}
        output_json_dict['categories'].append(category_info)
    output_file = os.path.join(output_dir, output_file)
    with open(output_file, 'w',encoding='utf-8') as f:
        output_json = json.dumps(output_json_dict,ensure_ascii=False,indent=4)
        f.write(output_json)
output_dir = '/data/VOCdevkit/'
output_file = "instance_train.json"
voc_xmls_to_cocojson(ann_paths, label2id, output_dir, output_file)
Start converting !


100%|██████████| 47102/47102 [00:05<00:00, 7998.80it/s] 

同理验证集也跑一次

label2id, ann_paths = voc_get_label_anno("/data/VOCdevkit/valid.txt","/data/VOCdevkit/label_list.txt")
output_dir = '/data/VOCdevkit/'
output_file = "instance_valid.json"
voc_xmls_to_cocojson(ann_paths, label2id, output_dir, output_file)
Start converting !


100%|██████████| 5237/5237 [00:01<00:00, 4246.70it/s]

你可能感兴趣的:(数据标注及转换,目标检测,计算机视觉,深度学习)