news 2026/3/28 1:03:27

从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/3/13 23:09:09

PNG还是JPG?人像卡通化格式选择避坑指南

PNG还是JPG&#xff1f;人像卡通化格式选择避坑指南 在使用人像卡通化工具时&#xff0c;你是否遇到过这样的困惑&#xff1a;明明参数调得刚刚好&#xff0c;生成效果也惊艳&#xff0c;可保存后图片却发灰、模糊、边缘锯齿明显&#xff0c;甚至出现奇怪的色块&#xff1f;或…

作者头像 李华
网站建设 2026/3/27 15:28:49

PDF-Extract-Kit-1.0效果展示:PDF中多级列表(编号/项目符号)结构还原

PDF-Extract-Kit-1.0效果展示&#xff1a;PDF中多级列表&#xff08;编号/项目符号&#xff09;结构还原 你有没有遇到过这样的情况&#xff1a;一份写得非常规范的PDF技术文档&#xff0c;里面用了一整套清晰的多级编号列表——比如“1.1 → 1.1.1 → ● → ◦”这样层层嵌套…

作者头像 李华
网站建设 2026/3/13 23:02:57

Clawdbot整合Qwen3:32B惊艳效果:Web网关下PDF解析+问答一体化演示

Clawdbot整合Qwen3:32B惊艳效果&#xff1a;Web网关下PDF解析问答一体化演示 1. 为什么这个组合让人眼前一亮 你有没有遇到过这样的场景&#xff1a;手头有一堆PDF技术文档&#xff0c;想快速查某个API参数却要一页页翻&#xff1f;或者客户发来十几页合同&#xff0c;临时需…

作者头像 李华
网站建设 2026/3/14 4:05:34

coze-loop作品分享:10个GitHub热门项目中低效循环的AI优化改造记录

coze-loop作品分享&#xff1a;10个GitHub热门项目中低效循环的AI优化改造记录 1. 什么是coze-loop&#xff1f;一个专治“写得慢、跑得慢、看不懂”的AI代码医生 你有没有遇到过这样的时刻&#xff1a; 翻开自己半年前写的Python脚本&#xff0c;第一眼就懵了——这循环嵌套…

作者头像 李华
网站建设 2026/3/25 2:53:17

批量处理Excel地址?MGeo+pandas轻松应对

批量处理Excel地址&#xff1f;MGeopandas轻松应对 你是否遇到过这样的场景&#xff1a;手头有一份包含上万条地址的Excel表格&#xff0c;需要快速判断其中两列地址是否指向同一地点&#xff1f;比如“杭州市西湖区文三路123号”和“杭州西湖区文三路123号”&#xff0c;仅因…

作者头像 李华
网站建设 2026/3/27 15:54:08

小白也能懂的语音合成:IndexTTS 2.0从0开始教学

小白也能懂的语音合成&#xff1a;IndexTTS 2.0从0开始教学 你有没有过这样的经历&#xff1f; 剪完一段3秒的短视频&#xff0c;反复对口型&#xff0c;配音却总差半拍&#xff1b; 想给自己的vlog配个有情绪的声音&#xff0c;结果生成的语音像机器人念说明书&#xff1b; 朋…

作者头像 李华