news 2026/5/30 17:21:46

从COCO到YOLOv5:高效实现Json标签到Txt格式的自动化转换

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从COCO到YOLOv5:高效实现Json标签到Txt格式的自动化转换

1. 为什么需要从COCO格式转换到YOLOv5格式

当你开始一个目标检测项目时,可能会遇到各种不同格式的标注数据。COCO格式和YOLO格式是目前最常用的两种标注格式,但它们有着完全不同的数据组织方式。COCO格式通常以单个json文件存储整个数据集的标注信息,而YOLOv5则需要为每张图片单独准备一个txt文件。

这种差异在实际项目中会带来不少麻烦。比如我最近接手的一个交通标志检测项目,客户提供的就是COCO格式的标注数据,但团队决定使用YOLOv5进行模型训练。这就必须先把数据转换成YOLOv5能识别的格式。转换过程中最大的挑战是要确保坐标系的正确转换和归一化处理,稍有不慎就会导致模型训练效果大打折扣。

2. 理解COCO和YOLOv5的标注格式差异

2.1 COCO格式的组成结构

COCO格式的标注文件是一个结构化的json文件,主要包含三个关键部分:

  • images:记录所有图片的基本信息,包括文件名、尺寸和唯一ID
  • annotations:存储所有标注框的详细信息,包括所属图片ID、类别ID和边界框坐标
  • categories:定义所有类别的名称和对应ID

举个例子,一个典型的COCO标注片段可能长这样:

{ "images": [ { "file_name": "013856.jpg", "height": 1080, "width": 1920, "id": 13856 } ], "annotations": [ { "image_id": 13856, "category_id": 2, "bbox": [541, 517, 79, 102] } ], "categories": [ {"id": 1, "name": "Car"}, {"id": 2, "name": "Pedestrian"} ] }

2.2 YOLOv5格式的要求

YOLOv5需要的标注格式则简单得多,每个图片对应一个同名的txt文件,每行表示一个目标对象,格式为:

<class_id> <x_center> <y_center> <width> <height>

其中所有坐标值都是相对于图片宽高的归一化值(0-1之间)。比如上面的COCO标注转换成YOLOv5格式会是:

1 0.2817708 0.5287037 0.0411458 0.0944444

3. 转换过程的关键步骤

3.1 解析COCO JSON文件

首先需要用Python的json模块加载文件内容:

import json with open('train.json', 'r') as f: coco_data = json.load(f)

解析后我们可以获取三个主要部分:

images = coco_data['images'] annotations = coco_data['annotations'] categories = coco_data['categories']

3.2 创建YOLOv5所需的目录结构

YOLOv5期望的数据目录结构通常是这样的:

dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/

我们可以用以下代码创建这个结构:

import os os.makedirs('dataset/images/train', exist_ok=True) os.makedirs('dataset/labels/train', exist_ok=True)

3.3 坐标转换与归一化处理

这是整个转换过程最关键的步骤。COCO的bbox格式是[x_top_left, y_top_left, width, height],而YOLOv5需要的是[x_center, y_center, width, height],并且所有值都要归一化。

转换公式如下:

def coco_to_yolo(bbox, img_width, img_height): x_tl, y_tl, w, h = bbox x_center = (x_tl + w/2) / img_width y_center = (y_tl + h/2) / img_height width = w / img_width height = h / img_height return [x_center, y_center, width, height]

4. 完整转换代码实现

下面是一个完整的转换脚本,包含了错误处理和日志记录:

import json import os from tqdm import tqdm def convert_coco_to_yolo(json_path, output_dir): # 加载COCO标注文件 with open(json_path, 'r') as f: coco_data = json.load(f) # 创建输出目录 os.makedirs(output_dir, exist_ok=True) # 构建图片ID到文件名的映射 img_id_to_info = {img['id']: img for img in coco_data['images']} # 构建类别ID映射(COCO ID可能不连续,需要重新映射) categories = {cat['id']: idx for idx, cat in enumerate(coco_data['categories'])} # 处理每个标注 for ann in tqdm(coco_data['annotations'], desc="Processing annotations"): img_info = img_id_to_info.get(ann['image_id']) if not img_info: continue # 获取图片尺寸 img_w, img_h = img_info['width'], img_info['height'] # 转换坐标 yolo_bbox = coco_to_yolo(ann['bbox'], img_w, img_h) # 获取对应的类别ID(从0开始) class_id = categories[ann['category_id']] # 准备写入内容 line = f"{class_id} {' '.join(map(str, yolo_bbox))}\n" # 写入到对应的txt文件 txt_path = os.path.join(output_dir, f"{os.path.splitext(img_info['file_name'])[0]}.txt") with open(txt_path, 'a') as f: f.write(line) def coco_to_yolo(bbox, img_w, img_h): x, y, w, h = bbox x_center = (x + w/2) / img_w y_center = (y + h/2) / img_h width = w / img_w height = h / img_h return [x_center, y_center, width, height] # 使用示例 convert_coco_to_yolo('train.json', 'dataset/labels/train')

5. 常见问题与解决方案

5.1 类别ID不一致问题

COCO数据集的类别ID可能不是从0开始的连续数字。比如官方COCO数据集的ID就是从1开始,而且中间有间隔。这会导致YOLOv5训练时报错,因为YOLO默认期望类别ID是连续的(0到n-1)。

解决方法是在转换时重新映射类别ID:

categories = {cat['id']: idx for idx, cat in enumerate(coco_data['categories'])}

5.2 坐标归一化错误

如果忘记做归一化处理,或者归一化计算错误,会导致模型完全无法学习。常见错误包括:

  • 忘记除以图片宽高
  • 使用绝对坐标而不是相对坐标
  • 中心点计算错误

建议在转换后随机检查几个样本,确认坐标值都在0-1范围内。

5.3 图片与标注文件不匹配

有时图片文件名和标注文件名可能不一致,导致训练时找不到对应标注。解决方法包括:

  • 确保文件名(不含扩展名)完全一致
  • 检查是否有隐藏字符或空格
  • 统一使用小写文件名

6. 验证转换结果

转换完成后,强烈建议可视化检查结果。可以使用以下代码随机检查几张图片:

import cv2 import random def visualize_yolo_label(img_path, label_path): img = cv2.imread(img_path) h, w = img.shape[:2] with open(label_path, 'r') as f: lines = f.readlines() for line in lines: class_id, xc, yc, bw, bh = map(float, line.strip().split()) # 转换回绝对坐标 x1 = int((xc - bw/2) * w) y1 = int((yc - bh/2) * h) x2 = int((xc + bw/2) * w) y2 = int((yc + bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 2) cv2.imshow('Preview', img) cv2.waitKey(0) # 随机检查5张图片 label_files = os.listdir('dataset/labels/train')[:5] for lf in label_files: img_file = lf.replace('.txt', '.jpg') visualize_yolo_label(f'dataset/images/train/{img_file}', f'dataset/labels/train/{lf}')

7. 性能优化技巧

当处理大规模数据集时,转换过程可能很耗时。以下是几个优化建议:

  1. 多进程处理:使用Python的multiprocessing模块并行处理
from multiprocessing import Pool def process_image(img_info): # 处理单张图片的转换逻辑 pass with Pool(4) as p: # 使用4个进程 p.map(process_image, coco_data['images'])
  1. 增量处理:先检查哪些文件已经转换过,避免重复工作

  2. 内存优化:对于特别大的json文件,可以考虑逐行读取而不是一次性加载

  3. 使用更快的JSON库:如orjson替代标准json模块

8. 与其他工具的集成

除了手动编写脚本,也可以考虑使用现成的转换工具:

  1. Roboflow:在线数据集转换平台,支持多种格式互转
  2. CVAT:标注工具内置格式转换功能
  3. MMYOLO:OpenMMLab提供的转换工具
  4. LabelImg:支持多种格式导出

不过根据我的经验,自己编写转换脚本还是最灵活的方式,特别是当你有特殊需求时。比如最近一个项目需要在转换过程中过滤掉某些特定类别的标注,这就很容易在自定义脚本中实现。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 13:43:43

内容创作好帮手!gpt-oss-20b-WEBUI生成高质量文案

内容创作好帮手&#xff01;gpt-oss-20b-WEBUI生成高质量文案 你是否经历过这样的时刻&#xff1a; 写产品介绍时卡在第一句&#xff0c;改了八遍还是像说明书&#xff1b; 赶营销方案到凌晨两点&#xff0c;文案却缺乏感染力&#xff1b; 客户临时要十版不同风格的社交媒体文…

作者头像 李华
网站建设 2026/5/27 15:34:14

Glyph模型深度体验:视觉-文本压缩到底强在哪

Glyph模型深度体验&#xff1a;视觉-文本压缩到底强在哪 大家好&#xff0c;最近在测试一批新开源的多模态推理镜像时&#xff0c;Glyph-视觉推理这个模型让我停下了手里的键盘——它不靠堆显存、不拼参数量&#xff0c;而是用一种“把文字画成图再看”的思路&#xff0c;重新…

作者头像 李华
网站建设 2026/5/22 22:29:20

3分钟搞定微博图片批量下载:从抓狂到躺平的效率革命

3分钟搞定微博图片批量下载&#xff1a;从抓狂到躺平的效率革命 【免费下载链接】weibo-image-spider 微博图片爬虫&#xff0c;极速下载、高清原图、多种命令、简单实用。 项目地址: https://gitcode.com/gh_mirrors/we/weibo-image-spider 你是不是也遇到过这样的情况…

作者头像 李华
网站建设 2026/5/21 3:43:32

跨平台位置模拟安全工具:重新定义iOS虚拟定位技术

跨平台位置模拟安全工具&#xff1a;重新定义iOS虚拟定位技术 【免费下载链接】iFakeLocation Simulate locations on iOS devices on Windows, Mac and Ubuntu. 项目地址: https://gitcode.com/gh_mirrors/if/iFakeLocation 在数字时代&#xff0c;你的iPhone地理位置可…

作者头像 李华