[MMDetection]VOC数据格式转为COCO数据格式


 以下脚本可以根据创建VOC格式数据集转换为COCO数据集

其中文件组织格式如下

VOC2007

        ------Annotations

                ------***********.xml

                ------***********.xml

       -------ImageSets

                ------train.txt 

                ------test.txt

        -------JPEGImages

                ------***********.jpg

                ------***********.jpg

     

COCO2017

        ------train

                ------annotations

                        ------train.json

                ------images

                        ------***********.jpg

                        ------***********.jpg

       -------test

                ------annotations 

                        ------test.json

                ------images

                        ------***********.jpg

                        ------***********.jpg

#!/usr/bin/python
# xml是voc的格式
# json是coco的格式
import sys, os, json, glob
import xml.etree.ElementTree as ET
import shutil
INITIAL_BBOXIds = 1
# PREDEF_CLASSE = {}
# 类别名
PREDEF_CLASSE = {'DT_SUBSIDENCE':0, 'PIP':1, 'NET':2, 'GROUND_LAMP':3, 'DT_CRACK':4, 'PIP_S':5, 'DT_GAP':6}



# function
def get(root, name):
    return root.findall(name)


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 convert(xml_paths, out_json, mode = "train"):
    json_dict = {'images': [], 'type': 'instances',
                 'categories': [], 'annotations': []}
    categories = PREDEF_CLASSE
    bbox_id = INITIAL_BBOXIds
    for image_id, xml_f in enumerate(xml_paths):

        # 进度输出
        # sys.stdout.write('\r>> Converting image %d/%d' % (
        #     image_id + 1, len(xml_paths)))
        # sys.stdout.flush()

        tree = ET.parse(xml_f)
        root = tree.getroot()

        # filename = get_and_check(root, 'frame', 1).text
        # print(type(xml_f))
        filename = xml_f.split(r"E:\VOC2007\Annotations")[1]   # VOC的annotations的路径
        filename = filename.split("\\")[1]
        filename = filename.split(".xml")[0]+".jpg"
        print("########################",filename,xml_f)
        if mode == "test":
            src = os.path.join(r"E:\VOC2007\JPEGImages",filename) # VOC的JPEGImages的路径
            dst = os.path.join(r"E:\COCO2017\test\images",filename) # 需要存放的COCOimage路径
            shutil.copyfile(src, dst)
        if mode == "train":
            src = os.path.join(r"E:\VOC2007\JPEGImages",filename)
            dst = os.path.join(r"E:COCO2017\train\images",filename)
            shutil.copyfile(src, dst)

        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 + 1}
        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 = max(categories.values()) + 1
                categories[category] = new_id
            category_id = categories[category]
            bbox = get_and_check(obj, 'bndbox', 1)
            xmin = int(get_and_check(bbox, 'xmin', 1).text) - 1
            ymin = int(get_and_check(bbox, 'ymin', 1).text) - 1
            xmax = int(get_and_check(bbox, 'xmax', 1).text)
            ymax = int(get_and_check(bbox, 'ymax', 1).text)
            if xmax <= xmin or ymax <= ymin:
                continue
            o_width = abs(xmax - xmin)
            o_height = abs(ymax - ymin)
            ann = {'area': o_width * o_height, 'iscrowd': 0, 'image_id': image_id + 1,
                   'bbox': [xmin, ymin, o_width, o_height], 'category_id': category_id,
                   'id': bbox_id, 'ignore': 0, 'segmentation': []}
            json_dict['annotations'].append(ann)
            bbox_id = bbox_id + 1

    for cate, cid in categories.items():
        cat = {'supercategory': 'none', 'id': cid, 'name': cate}
        json_dict['categories'].append(cat)

    # json_file = open(out_json, 'w')
    # json_str = json.dumps(json_dict)
    # json_file.write(json_str)
    # json_file.close() # 快
    json.dump(json_dict, open(out_json, 'w'), indent=4)  # indent=4 更加美观显示 慢


if __name__ == '__main__':
    # 1、读取VOC2007\ImagesSets\Main中的文件 得到测试集和训练集的图片名
    test_filenames = []
    train_filenames = []
    with open(r"E:\VOC2007\ImageSets\Main\test.txt") as f:
        for filename in f.readlines():
            test_filenames.append(filename.split('\n')[0])  # 去掉换行符 \n 
    with open(r"E:\VOC2007\ImageSets\Main\train.txt") as f:
        for filename in f.readlines():
            train_filenames.append(filename.split('\n')[0])  
    print(test_filenames)
    print(train_filenames)

    # 2、分别拼凑出 训练 和 测试 所需要的xml 路径
    xml_path = r'E:\VOC2007\Annotations'  # 改一下读取xml文件位置
    train_xml_files = []
    test_xml_files = []
    for train_filename in train_filenames:
        train_xml_file = os.path.join(xml_path,train_filename) + '.xml'   # 拼接路径 加上后缀
        # print(train_xml_file)
        train_xml_files.append(train_xml_file)

    for test_filename in test_filenames:
        test_xml_file = os.path.join(xml_path,test_filename) + '.xml'
        # print(test_xml_file)
        test_xml_files.append(test_xml_file)

    print(test_xml_files)
    print(train_xml_files)

    # 3、转换数据
    convert(test_xml_files, r'E:\COCO2017\test\annotations\test.json',mode="test")  # 这里是生成的json保存位置,改一下
    convert(train_xml_files, r'E:\COCO2017\train\annotations\train.json',mode="train")  # 这里是生成的json保存位置,改一下
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
你可以使用一些工具和代码来将VOC格式数据转换为COCO格式,以便在mmdetection中使用。以下是一种可能的方法: 1. 首先,确保你已经安装了`mmcv`和`mmdet`库。你可以使用以下命令安装它们: ``` pip install mmcv-full mmdet ``` 2. 下载并解压VOC数据集,并将其组织为以下结构: ``` VOCdevkit/ ├── VOC2007 │ ├── Annotations │ ├── ImageSets │ └── JPEGImages └── VOC2012 ├── Annotations ├── ImageSets └── JPEGImages ``` 3. 创建一个Python脚本,例如`voc2coco.py`,并使用以下代码来进行VOCCOCO格式转换: ```python import os import json from xml.etree.ElementTree import Element, SubElement, tostring from xml.dom.minidom import parseString def parse_voc_annotation(ann_dir, img_dir, labels=[]): # 读取VOC标注文件和图像文件夹 ann_files = sorted(os.listdir(ann_dir)) img_files = sorted(os.listdir(img_dir)) assert len(ann_files) == len(img_files), "Number of annotation files doesn't match number of image files" # 构建COCO格式标注数据结构 coco_data = { "images": [], "annotations": [], "categories": [] } category_id = 0 for i, ann_file in enumerate(ann_files): img_file = img_files[i] img_id = i + 1 # 解析VOC标注文件 ann_path = os.path.join(ann_dir, ann_file) tree = parseString(open(ann_path).read()) root = tree.documentElement # 获取图像信息 img_width = int(root.getElementsByTagName("width")[0].childNodes[0].data) img_height = int(root.getElementsByTagName("height")[0].childNodes[0].data) img_name = img_file.split(".")[0] # 添加图像信息到coco_data["images"] coco_data["images"].append({ "file_name": img_file, "height": img_height, "width": img_width, "id": img_id }) # 解析VOC标注信息 objects = root.getElementsByTagName("object") for obj in objects: name = obj.getElementsByTagName("name")[0].childNodes[0].data if name not in labels: labels.append(name) category_id = labels.index(name) + 1 bbox = obj.getElementsByTagName("bndbox")[0] xmin = int(bbox.getElementsByTagName("xmin")[0].childNodes[0].data) ymin = int(bbox.getElementsByTagName("ymin")[0].childNodes[0].data) xmax = int(bbox.getElementsByTagName("xmax")[0].childNodes[0].data) ymax = int(bbox.getElementsByTagName("ymax")[0].childNodes[0].data) width = xmax - xmin height = ymax - ymin # 添加标注信息到coco_data["annotations"] coco_data["annotations"].append({ "image_id": img_id, "category_id": category_id, "bbox": [xmin, ymin, width, height], "area": width * height, "iscrowd": 0, "id": len(coco_data["annotations"]) + 1 }) # 构建coco_data["categories"] for i, label in enumerate(labels): coco_data["categories"].append({ "id": i + 1, "name": label, "supercategory": "object" }) return coco_data if __name__ == '__main__': ann_dir = 'VOCdevkit/VOC2007/Annotations' img_dir = 'VOCdevkit/VOC2007/JPEGImages' labels = [] coco_data = parse_voc_annotation(ann_dir, img_dir, labels) # 保存为COCO格式的JSON文件 with open('annotations.json', 'w') as f: json.dump(coco_data, f) ``` 4. 运行`voc2coco.py`脚本,它将生成一个名为`annotations.json`的COCO格式标注文件。 现在,你可以使用这个生成的COCO格式的标注文件在mmdetection中进行训练或评估。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

开始学AI

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

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

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

打赏作者

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

抵扣说明:

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

余额充值