Labelme标注数据喂给MMDetection/YOLO?先搞定COCO格式转换这个坑
Labelme标注数据转COCO格式实战指南与MMDetection/YOLO无缝对接当你用Labelme精心标注完数百张图像准备在MMDetection或YOLO框架中大展身手时突然发现模型根本不认你的标注文件——这种挫败感我深有体会。本文将带你穿越从Labelme标注到主流检测框架训练的全流程重点解决那些官方文档里没写的魔鬼细节。1. 为什么COCO格式成为行业标准COCOCommon Objects in Context格式之所以被MMDetection、Detectron2、YOLOv5/v8等主流框架广泛支持源于其设计的完备性。它不仅支持目标检测还能完美表达实例分割、关键点检测等复杂任务。与Labelme的JSON文件相比COCO格式的核心优势在于统一的数据结构所有标注信息整合在单个annotations.json中高效的存储方式使用RLERun-Length Encoding压缩分割掩膜丰富的元信息包含图像尺寸、许可证、类别超类等完整描述典型的COCO数据集目录结构如下coco_dataset/ ├── annotations/ │ ├── instances_train2017.json │ └── instances_val2017.json ├── train2017/ │ ├── 000000000009.jpg │ └── ... └── val2017/ ├── 000000000139.jpg └── ...2. Labelme转COCO格式的三种实战方案2.1 官方labelme2coco脚本深度解析Labelme官方提供的转换脚本位于examples/instance_segmentation目录下。这个方案的优势是官方维护但需要注意几个关键参数python labelme2coco.py \ --input_dir ./labelme_annotations \ --output_dir ./coco_dataset \ --labels labels.txt关键文件labels.txt的编写规范__ignore__ cat dog person注意第一行必须是__ignore__后续每行一个类别名称顺序决定了最终的category_id转换过程中常见的报错及解决方案错误类型可能原因解决方法KeyError: imageData图片路径变动导致数据丢失使用--noviz跳过可视化或检查图片路径ImportError: pycocotools缺少依赖库pip install pycocotoolsValueError: invalid literalJSON文件损坏用json.tool验证文件完整性2.2 改进版转换工具labelme2coco.py针对官方脚本的不足我优化了一个增强版本主要改进包括自动处理相对/绝对路径问题支持多级目录结构扫描添加类别统计功能核心改进代码片段def validate_image_path(img_path, root_dir): 智能处理图片路径问题 if not osp.exists(img_path): # 尝试在标注文件同级目录查找 base_path osp.join(root_dir, osp.basename(img_path)) if osp.exists(base_path): return base_path # 尝试在JPEGImages子目录查找 jpeg_path osp.join(root_dir, JPEGImages, osp.basename(img_path)) if osp.exists(jpeg_path): return jpeg_path return img_path2.3 可视化验证工具开发转换后必须验证数据完整性我推荐使用这个简单的可视化检查脚本import json from PIL import Image, ImageDraw import matplotlib.pyplot as plt def visualize_coco_annotation(json_path, image_dir): with open(json_path) as f: data json.load(f) # 随机选择一张带标注的图片 img_info data[images][0] anns [a for a in data[annotations] if a[image_id] img_info[id]] img Image.open(osp.join(image_dir, img_info[file_name])) draw ImageDraw.Draw(img) for ann in anns: bbox ann[bbox] draw.rectangle([bbox[0], bbox[1], bbox[0]bbox[2], bbox[1]bbox[3]], outlinered, width2) # 绘制分割多边形 for seg in ann[segmentation]: draw.polygon(seg, outlinegreen) plt.imshow(img) plt.show()3. 与训练框架对接的最后一公里问题3.1 MMDetection框架适配技巧在MMDetection中使用转换后的数据需特别注意dataset_type和data_root的配置。以下是典型配置示例dataset_type CocoDataset data_root data/coco/ train_pipeline [ dict(typeLoadImageFromFile), dict(typeLoadAnnotations, with_bboxTrue, with_maskTrue), dict(typeResize, img_scale(1333, 800), keep_ratioTrue), dict(typeRandomFlip, flip_ratio0.5), dict(typeNormalize, mean[123.675, 116.28, 103.53], std[58.395, 57.12, 57.375]), dict(typePad, size_divisor32), dict(typeDefaultFormatBundle), dict(typeCollect, keys[img, gt_bboxes, gt_labels, gt_masks]), ]常见问题排查表现象可能原因解决方案加载数据时卡住图像路径错误检查file_name是否为相对路径类别ID不匹配labels.txt顺序与训练配置不一致统一类别定义顺序分割掩膜异常RLE编码问题重新生成COCO格式并验证3.2 YOLOv5/v8的特殊处理YOLO系列虽然也支持COCO格式但有其特殊要求目录结构要求yolo_dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/使用ultralytics库提供的转换工具from ultralytics.data.converter import coco2yolo coco2yolo( json_fileannotations.json, use_segmentsTrue, save_diryolo_labels )关键参数说明use_segments: 是否保留分割信息cls91to80: 将COCO91类映射到YOLO80类4. 高级技巧与性能优化4.1 大规模数据集处理方案当处理上万张图片时原始方法可能遇到内存问题。这里推荐分块处理策略def chunked_conversion(input_dir, output_dir, chunk_size1000): json_files glob.glob(osp.join(input_dir, *.json)) for i in range(0, len(json_files), chunk_size): chunk_files json_files[i:i chunk_size] output_json osp.join(output_dir, fannotations_{i}.json) labelme2coco(chunk_files, output_json)4.2 标注质量自动检查在转换过程中集成质量检查可以节省后期调试时间def check_annotation_quality(ann): 检查标注是否存在明显问题 issues [] # 检查bbox是否超出图像边界 if ann[bbox][0] 0 or ann[bbox][1] 0: issues.append(负坐标bbox) # 检查分割区域面积与bbox面积比率 bbox_area ann[bbox][2] * ann[bbox][3] if ann[area] / bbox_area 0.5: issues.append(分割区域过小) return issues4.3 自定义扩展字段有时我们需要在COCO格式中添加自定义字段如难度等级只需扩展标准格式{ images: [...], annotations: [ { ..., custom_fields: { difficulty: 3, occlusion: 0.5 } } ], categories: [...] }在MMDetection中可以通过自定义CustomCocoDataset来加载这些字段。