news 2026/4/16 9:09:31

从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/4/16 9:04:26

AI 净界PPT美化助手:RMBG-1.4 提供高质量演讲配图素材

AI 净界PPT美化助手&#xff1a;RMBG-1.4 提供高质量演讲配图素材 1. 为什么做PPT总卡在配图这一步&#xff1f; 你是不是也经历过—— 花半小时写完一页“市场增长策略”&#xff0c;却对着一张带白边的截图发愁&#xff1a; 背景太杂&#xff1f;裁不干净&#xff1b; 人物…

作者头像 李华
网站建设 2026/4/15 15:38:19

GLM-4v-9b部署案例:教育机构课件截图自动生成习题与答案

GLM-4v-9b部署案例&#xff1a;教育机构课件截图自动生成习题与答案 1. 为什么教育机构需要这个能力&#xff1f; 你有没有见过这样的场景&#xff1a;一位中学物理老师凌晨一点还在电脑前&#xff0c;把PPT里的电路图一张张截下来&#xff0c;手动敲出5道选择题、2道填空题&…

作者头像 李华
网站建设 2026/4/16 9:06:09

BEYOND REALITY Z-Image环境配置:CUDA 12.1 + PyTorch 2.3 + BF16支持验证

BEYOND REALITY Z-Image环境配置&#xff1a;CUDA 12.1 PyTorch 2.3 BF16支持验证 1. 为什么这套配置值得专门验证&#xff1f; 你可能已经试过不少文生图模型&#xff0c;但大概率遇到过这些情况&#xff1a;生成一张人像&#xff0c;脸是黑的&#xff1b;调高步数后细节反…

作者头像 李华
网站建设 2026/4/16 9:05:22

CLAP音频分类实战:从上传到分类只需3步

CLAP音频分类实战&#xff1a;从上传到分类只需3步 你有没有遇到过这样的场景&#xff1a;一段现场录制的环境音&#xff0c;夹杂着风声、隐约的鸟鸣和远处模糊的人声&#xff0c;你想快速判断里面是否包含“施工噪音”&#xff1f;或者收到一段客户投诉录音&#xff0c;需要在…

作者头像 李华
网站建设 2026/4/16 12:47:05

实测Linux开机自启方案,测试启动脚本效果超预期

实测Linux开机自启方案&#xff0c;测试启动脚本效果超预期 1. 为什么需要实测&#xff1f;一个被低估的工程细节 你有没有遇到过这样的情况&#xff1a;写好了开机自启脚本&#xff0c;信心满满地配置完&#xff0c;重启后却发现——什么都没发生&#xff1f; 不是脚本写错…

作者头像 李华