You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将COCO JSON转YOLOv8分割格式?标签异常问题排查

修复COCO JSON转YOLOv8分割标签的脚本

原脚本生成的标签在YOLOv8训练时异常,核心问题是分割坐标归一化错误,以及部分细节处理不到位。以下是修正后的完整脚本,适配不同尺寸的图片:

import json
import os
from tqdm import tqdm

def convert_coco_to_yolov8(coco_file):
    # 加载COCO JSON文件
    with open(coco_file, 'r', encoding='utf-8') as f:
        coco = json.load(f)

    # 整理类别映射:COCO的ID可能不连续,转为从0开始的索引
    categories = {cat['id']: idx for idx, cat in enumerate(coco['categories'])}

    # 创建标签输出目录
    os.makedirs('labels', exist_ok=True)

    # 按图片遍历处理
    for image in tqdm(coco['images'], desc='转换图片标签'):
        image_id = image['id']
        filename = image['file_name']
        img_width = image['width']
        img_height = image['height']

        # 生成标签文件名:替换原后缀为.txt
        label_filename = os.path.splitext(filename)[0] + '.txt'
        label_path = os.path.join('labels', label_filename)

        with open(label_path, 'w', encoding='utf-8') as f:
            # 筛选当前图片的所有标注
            img_annotations = [ann for ann in coco['annotations'] if ann['image_id'] == image_id]
            for ann in img_annotations:
                # 处理类别ID:转为YOLOv8要求的从0开始的索引
                label_id = categories[ann['category_id']]

                # 处理bbox(YOLOv8分割标签建议保留bbox,也可根据需求省略)
                xmin, ymin, bbox_w, bbox_h = ann['bbox']
                # 归一化bbox坐标
                xcen = (xmin + bbox_w / 2) / img_width
                ycen = (ymin + bbox_h / 2) / img_height
                norm_w = bbox_w / img_width
                norm_h = bbox_h / img_height

                # 处理分割坐标:COCO的segmentation是[x1,y1,x2,y2,...]列表,交替归一化x/y
                segmentation_str = []
                for seg in ann['segmentation']:
                    # 遍历每一对x,y坐标
                    for i in range(0, len(seg), 2):
                        x = seg[i] / img_width
                        y = seg[i+1] / img_height
                        segmentation_str.append(f'{x:.6f} {y:.6f}')
                # 拼接所有分割点
                seg_points = ' '.join(segmentation_str)

                # 写入标签行:格式为 类别ID 归一化xcen 归一化ycen 归一化w 归一化h 分割点1x 分割点1y ...
                line = f'{label_id} {xcen:.6f} {ycen:.6f} {norm_w:.6f} {norm_h:.6f} {seg_points}\n'
                f.write(line)

关键修正点说明

  • 分割坐标归一化:原脚本将所有分割点都除以图片宽度,现在改为x坐标除以宽度、y坐标除以高度,完全符合YOLOv8的归一化规则。
  • 类别ID映射:COCO的类别ID通常从1开始,YOLOv8要求类别ID从0开始连续索引,新增映射逻辑避免训练时类别索引错误。
  • 文件名兼容:改用os.path.splitext处理文件名,支持.jpg、.png等多种格式,解决仅适配.png的局限性。
  • 效率优化:提前筛选当前图片的所有标注,减少循环内的判断次数,提升转换速度。
  • 精度控制:归一化坐标保留6位小数,避免精度丢失导致的标签偏移。

验证方法

转换完成后可随机抽查标签文件:

  1. 确认类别ID从0开始连续
  2. 检查bbox和分割点的归一化值是否在0-1范围内
  3. 对照原图片标注,验证分割点位置是否匹配

内容的提问来源于stack exchange,提问作者suhail shaji

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 01:12:36