Labelme转COCO格式终极指南零基础实现自动化实例分割数据集转换在计算机视觉项目中数据标注是模型训练前的关键环节。Labelme作为一款开源的图像标注工具因其简单易用和强大的多边形标注功能成为许多研究者和开发者的首选。但当我们需要将Labelme生成的JSON标注文件转换为COCO格式时往往会遇到各种问题——格式不匹配、标签丢失、路径错误等。本文将提供一个完整的解决方案从环境配置到错误处理帮你彻底摆脱手动转换的烦恼。1. 环境准备与工具链搭建1.1 必备依赖安装转换过程需要以下Python包支持pip install labelme pycocotools numpy imgviz pillow注意在Windows系统上安装pycocotools可能会遇到编译错误建议使用预编译版本pip install pycocotools-windows1.2 项目目录结构规范合理的文件组织能避免80%的路径问题。推荐采用以下结构project_root/ ├── labelme_annotations/ # 原始Labelme标注文件 │ ├── image1.jpg │ ├── image1.json │ ├── image2.jpg │ └── image2.json ├── labels.txt # 类别标签文件 └── coco_output/ # 转换输出目录自动创建labels.txt文件示例内容__ignore__ cat dog person2. 核心转换脚本解析2.1 完整转换脚本实现以下脚本在原版基础上增加了错误处理、进度显示和格式验证功能#!/usr/bin/env python import argparse import json import os import sys from pathlib import Path import numpy as np import labelme from labelme import utils try: from pycocotools import mask as maskUtils except ImportError: print(Error: pycocotools not installed. Run: pip install pycocotools) sys.exit(1) class LabelmeToCocoConverter: def __init__(self, args): self.args args self.check_dirs() self.coco { images: [], annotations: [], categories: self.load_categories(), } self.image_id 0 self.annotation_id 1 def load_categories(self): with open(self.args.labels) as f: lines [line.strip() for line in f.readlines()] return [ {id: idx, name: name, supercategory: object} for idx, name in enumerate(lines) if name ! __ignore__ ] def check_dirs(self): if not os.path.exists(self.args.input_dir): raise FileNotFoundError(fInput directory not found: {self.args.input_dir}) os.makedirs(self.args.output_dir, exist_okTrue) def process_image(self, json_path): try: label_file labelme.LabelFile(filenamestr(json_path)) image_path Path(json_path).with_suffix(.jpg) # 添加图像信息 img_arr utils.img_data_to_arr(label_file.imageData) self.coco[images].append({ id: self.image_id, file_name: image_path.name, height: img_arr.shape[0], width: img_arr.shape[1], }) # 处理每个标注形状 for shape in label_file.shapes: self.process_shape(shape, img_arr.shape) self.image_id 1 print(fProcessed: {json_path.name}) except Exception as e: print(fError processing {json_path}: {str(e)}) def process_shape(self, shape, img_shape): points shape[points] label shape[label] # 多边形转COCO格式 segmentation [np.asarray(points).flatten().tolist()] mask utils.shape_to_mask(img_shape[:2], points, shape.get(shape_type, polygon)) # 计算边界框和面积 mask np.asfortranarray(mask.astype(np.uint8)) encoded_mask maskUtils.encode(mask) bbox maskUtils.toBbox(encoded_mask).tolist() area float(maskUtils.area(encoded_mask)) # 添加到COCO标注 self.coco[annotations].append({ id: self.annotation_id, image_id: self.image_id, category_id: self.get_category_id(label), segmentation: segmentation, area: area, bbox: bbox, iscrowd: 0, }) self.annotation_id 1 def get_category_id(self, label): for cat in self.coco[categories]: if cat[name] label: return cat[id] raise ValueError(fLabel {label} not found in categories) def save_coco_json(self): output_path Path(self.args.output_dir) / annotations.json with open(output_path, w) as f: json.dump(self.coco, f, indent2) print(fCOCO format annotations saved to: {output_path}) def main(): parser argparse.ArgumentParser() parser.add_argument(input_dir, helpDirectory containing Labelme JSON files) parser.add_argument(output_dir, helpOutput directory for COCO format) parser.add_argument(--labels, requiredTrue, helpPath to labels.txt file) args parser.parse_args() converter LabelmeToCocoConverter(args) json_files list(Path(args.input_dir).glob(*.json)) print(fFound {len(json_files)} JSON files to process) for json_file in json_files: converter.process_image(json_file) converter.save_coco_json() if __name__ __main__: main()2.2 关键功能改进点相比原始脚本这个版本做了以下重要优化错误处理机制文件不存在检查标签缺失验证图像数据解析异常捕获进度可视化显示处理文件计数实时打印当前处理文件完成时输出统计信息代码结构化使用面向对象方式组织分离不同功能到独立方法增加类型提示和文档字符串3. 实战操作指南3.1 完整转换流程准备标注数据mkdir -p dataset/labelme # 将Labelme生成的.jpg和.json文件放入dataset/labelme创建标签文件echo -e __ignore__\ncat\ndog\nperson labels.txt执行转换命令python labelme2coco.py dataset/labelme dataset/coco --labels labels.txt验证输出结果tree dataset/coco预期输出结构dataset/coco/ ├── annotations.json └── JPEGImages ├── image1.jpg └── image2.jpg3.2 常见问题解决方案问题现象可能原因解决方案Label not found错误标签文件中缺少对应类别检查labels.txt是否包含所有标注类别JSON解析失败文件损坏或格式错误使用jsonlint验证文件有效性图像尺寸不匹配图片被修改但未更新标注重新生成标注或恢复原始图片空边界框无效的多边形标注在Labelme中检查并修正标注点4. 高级应用技巧4.1 批量处理技巧使用GNU parallel加速大规模数据集转换find dataset/labelme -name *.json | parallel -j 8 python labelme2coco.py {} {.}_coco --labels labels.txt4.2 可视化验证转换后立即检查标注是否正确from pycocotools.coco import COCO import matplotlib.pyplot as plt coco COCO(dataset/coco/annotations.json) img_ids coco.getImgIds() img_info coco.loadImgs(img_ids[0])[0] plt.imshow(plt.imread(fdataset/coco/JPEGImages/{img_info[file_name]})) ann_ids coco.getAnnIds(imgIdsimg_info[id]) for ann in coco.loadAnns(ann_ids): mask coco.annToMask(ann) plt.imshow(mask, alpha0.5) plt.show()4.3 自定义扩展添加额外元数据 修改process_image方法将EXIF信息等加入COCO格式支持视频帧标注 扩展脚本处理视频序列的特殊命名约定多任务支持 同时生成目标检测和实例分割的标注# 在process_shape方法中添加 if shape.get(attributes, {}).get(is_detection, False): # 生成检测专用标注 pass在实际项目中我发现最常出现的问题是标签不一致。建议在转换前先运行标签校验脚本import collections from pathlib import Path def check_labels(json_dir, label_file): used_labels collections.Counter() for json_path in Path(json_dir).glob(*.json): with open(json_path) as f: data json.load(f) for shape in data[shapes]: used_labels[shape[label]] 1 with open(label_file) as f: defined_labels {line.strip() for line in f} print(Undefined labels:, set(used_labels) - defined_labels)