如何将VOC XML文件转化成COCO数据格式

本文详细介绍了如何将VOC的XML标注文件转换为COCO数据格式,包括COCO数据结构的解析,XML文件内容的解析,并提供了一段Python代码示例进行转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数据转换实在是个烦人的工作,被折磨了很久决定抽出时间整理一下,仅供参考。

在一个项目中,我需要将已有的VOC的xml标注文件转化成COCO的数据格式,为了方便理解,文章按如下顺序介绍:

XML文件内容长什么样
COCO的数据格式长什么样
XML如何转化成COCO格式
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属于哪一类,例如Apple
bndbox:给出左上角和右下角的坐标
truncated:略
difficult:略

COCO长什么样?

COCO目录啥样?

不同于VOC,一张图片对应一个xml文件,coco是直接将所有图片以及对应的box信息写在了一个json文件里。通常整个coco目录长这样:
python coco |______annotations # 存放标注信息 | |__train.json | |__val.json | |__test.json |______trainset # 存放训练集图像 |______valset # 存放验证集图像 |______testset # 存放测试集图像

COCO的json文件啥样?

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

{
“info”: info,
“images”: [image],
“annotations”: [annotation],
“licenses”: [license],
}

info{
“year”: int,
“version”: str,
“description”: str,
“contributor”: str,
“url”: str,
“date_created”: datetime,
}
image{
“id”: int,
“width”: int,
“height”: int,
“file_name”: str,
“license”: int,
“flickr_url”: str,
“coco_url”: str,
“date_captured”: datetime,
}
license{
“id”: int,
“name”: str,
“url”: str,
}
是不是有点抽象?官网就是这样的,酸爽不酸爽,反正我看

### 将VOC XML文件转换COCO数据集格式 #### VOC XML文件结构 VOC XML文件通常包含有关图像及其对象的信息。具体来说,这些文件可能包括以下字段: - `folder`:表示图片所在的文件夹名称。 - `filename`:存储图像文件的名字(例如`at002eg001.jpg`)。 - `path`:提供到该图像的具体路径(如`path_to\at002eg001.jpg`)。 - `size`:描述图像尺寸的相关信息,比如宽度和高度。 - `object`:列举了存在于这张照片中的各个物体实例;对于每一个这样的实体而言,则会记录其类别以及边界框坐标等细节。 这种结构使得解析XML文档成为一种相对直接的任务,因为所有的必要组件都已经被清晰地标记出来了[^1]。 #### COCO JSON格式概述 相比之下,Common Objects in Context (COCO) 数据集采用JSON作为主要载体来保存同样的元数据。一个典型的COCO风格的JSON文件由几个顶级键组成——images, annotations 和 categories: - **Images**: 列表形式给出每张图的基本属性,像id、width、height还有file_name。 - **Annotations**: 对应于上述image列表里的每一项所含有的所有目标物的位置与大小说明,同样是以数组的方式呈现给定范围内的多个annotation条目。每个annotation至少应该有bbox(边框), image_id, category_id这几个成员变量。 - **Categories**: 定义了整个集合中存在的不同种类别的ID号同它们各自的name字符串之间的映射关系。 因此,在准备将Pascal VOC转译至MS-COCO的过程中,需要构建起这三层级联式的关联体系,并确保各类别标签的一致性和准确性[^2]。 #### 转换过程详解 为了实现从VOC XMLCOCO JSON的有效迁移,可以遵循下面的方法论来进行操作: 1. 初始化一个新的Python字典用来承载最终要导出的目标json内容; 2. 遍历输入源下的全部.xml文件并逐个读取其中的内容; 3. 解析单个xml节点获取对应的image metadata及objects list; 4. 基于已知的对象分类创建category entries填充categories部分; 5. 使用循环迭代通过计算得到的bounding box参数建立annotations records; 6. 把处理过的图片资料加入到images section里去; 7. 最终序列化完成后的复合型data structure为标准json string输出即可。 这里有一段简单的Python脚本示范了这一流程的一部分逻辑: ```python import os from xml.etree import ElementTree as ET import json def parse_voc_xml(xml_file_path): tree = ET.parse(xml_file_path) root = tree.getroot() filename = root.find('filename').text size = root.find('size') width = int(size.find('width').text) height = int(size.find('height').text) objects = [] for obj in root.findall('object'): name = obj.find('name').text bndbox = obj.find('bndbox') xmin = float(bndbox.find('xmin').text) ymin = float(bndbox.find('ymin').text) xmax = float(bndbox.find('xmax').text) ymax = float(bndbox.find('ymax').text) bbox_width = xmax - xmin bbox_height = ymax - ymin object_info = { 'name': name, 'bbox': [xmin, ymin, bbox_width, bbox_height], 'area': bbox_width * bbox_height } objects.append(object_info) return {'filename': filename, 'width': width, 'height': height, 'objects': objects} def voc_to_coco(voc_dir, output_json='output.json', dataset_type='train'): images = [] annotations = [] categories = [] # Assuming all .xml files are under the same directory with corresponding images. annotation_files = [f for f in os.listdir(voc_dir) if f.endswith('.xml')] global_annotation_id = 0 for idx, file in enumerate(annotation_files): img_data = parse_voc_xml(os.path.join(voc_dir, file)) image_entry = {"id": idx + 1, "file_name": img_data['filename'], "width": img_data['width'], "height": img_data['height']} images.append(image_entry) for obj_idx, obj in enumerate(img_data['objects']): cat_found = False for existing_cat in categories: if existing_cat["name"] == obj['name']: cat_found = True break if not cat_found: new_category = {"supercategory": "", "id": len(categories)+1, "name": obj['name']} categories.append(new_category) ann_entry = { "segmentation": [], "iscrowd": 0, "image_id": idx + 1, "bbox": obj['bbox'], "category_id": next((item for item in categories if item["name"] == obj['name']), None)['id'], "id": global_annotation_id + obj_idx + 1, "area": obj['area'] } annotations.append(ann_entry) global_annotation_id += len(img_data['objects']) coco_format = { "info": {}, "licenses": [], "type": "instances", "images": images, "annotations": annotations, "categories": categories } with open(output_json, mode="w", encoding="utf-8") as out_f: json.dump(coco_format, out_f) if __name__ == "__main__": voc_directory = './voc_annotations' # Replace this path according to your setup voc_to_coco(voc_directory) ``` 此代码片段展示了如何遍历指定目录下所有的`.xml`文件并将之转化为符合COCO规格的JSON文件。注意这段程序假设所有的标注文件(.xml)与其对应的实际图像位于同一位置,并且仅实现了基本的功能框架,实际应用时还需要考虑更多因素,例如错误处理机制或是更复杂的场景适应等问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值