labelme 实例分割标注与 VOC/COCO 数据集转换实战指南

labelme 实例分割标注与 VOC/COCO 数据集转换实战指南 labelme 实例分割标注与 VOC/COCO 数据集转换实战指南【免费下载链接】labelmeImage annotation with Python. Supports polygon, rectangle, circle, line, point, and AI-assisted annotation.项目地址: https://gitcode.com/gh_mirrors/la/labelme本指南以仓库中的 examples/instance_segmentation 为例完整讲解如何用 labelme 对图片进行实例分割标注并将标注结果一键转换为 Pascal VOC 与 MS COCO 两种主流数据格式。读完本文你将掌握--validate-label、--label-flags、--config等关键命令行参数的实际用法理解labelme2voc.py与labelme2coco.py的转换原理包括类别编号、实例合并、标签像素值约定并能独立复现从原始图片到可训练数据集的完整流水线。一、示例工程结构总览examples/instance_segmentation是一个完整的实例分割工作区同时包含标注前与转换后两个阶段的数据结构如下examples/instance_segmentation/ ├── data_annotated/ # 标注产物3 张图片 3 个 JSON 标注文件 ├── data_dataset_voc/ # labelme2voc.py 的转换输出 ├── data_dataset_coco/ # labelme2coco.py 的转换输出 ├── labelme2voc.py # VOC 格式转换脚本 ├── labelme2coco.py # COCO 格式转换脚本 ├── labels.txt # 类别清单VOC 20 类 └── README.md # 本文对应的官方说明其中data_annotated内含2011_000003.jpg、2011_000006.jpg、2011_000025.jpg三张示例图片及其同名.json标注文件data_dataset_voc与data_dataset_coco则是运行转换脚本后生成的成品数据集可直接对照验证你的转换结果。转换脚本依赖同目录下示例所需的 examples/utils.py 与 examples/tutorial/draw_label_png.py 等辅助工具。二、数据准备labels.txt 与标注 JSON 格式2.1 类别清单 labels.txt实例分割的第一步是定义类别清单。本示例的 labels.txt 内容如下__ignore__ _background_ aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person potted plant sofa train tv/monitor前两行是两个特殊约定需要特别注意__ignore__占位类别在转换时会被映射为忽略区域其像素值在 PNG 中记为255npy 中为-1用于遮盖不希望参与训练的物体或区域_background_背景类别像素值恒为0。其余 20 行即标准 Pascal VOC 的 20 个语义类别。标注时形状的 label 必须能在该清单中找到精确匹配否则后续转换会报错。2.2 标注 JSON 的结构以 data_annotated/2011_000003.json 为例labelme 4.x 的标注文件顶层结构为{ version: 4.0.0, flags: {}, shapes: [ { label: person, points: [[250.8, 107.3], [229.8, 119.3], ..., [270.8, 121.3]], group_id: 0, shape_type: polygon, flags: {} } ], imagePath: 2011_000003.jpg, imageData: null, imageHeight: 338, imageWidth: 500 }每个 shape 的关键字段含义字段含义实例分割中的角色label形状所属类别决定该形状写入类别层class 层的编号points顶点坐标列表定义多边形/矩形/圆等几何区域shape_type形状类型polygon/rectangle/circle/line/point/linestrip 等决定栅格化方式group_id实例分组标识可空实例分割的核心决定多个形状是否属于同一实例flags该形状的自定义标志不参与分割掩码仅作属性记录group_id 与实例划分是本例最值得注意的细节在2011_000003.json中前两个person形状共享group_id: 0说明它们是同一个人的两块多边形碎片转换时会被合并为一个实例而第三个person的group_id为null会作为独立实例处理。__ignore__形状则用于圈出画面中需要忽略的区域。这一约定直接决定了后续实例掩码的生成逻辑。三、启动标注命令行参数深度解析原文档给出的标注命令有两条分别对应两种典型配置场景。3.1 指定类别清单与颜色自动分配labelme data_annotated --labels labels.txt --validate-label exact --config {shape_color: {mode: auto, auto: {shift: -2}}}三个参数的作用--labels labels.txt指定类别清单文件。从 labelme/main.py 的解析逻辑看--labels既支持文件路径也支持逗号分隔的内联文本--validate-label exact开启标签校验。在 labelme/_config/init.py 中可以看到validate_label配置项只接受None与exact两种取值且启用时必须同时提供--labels否则启动会直接报错。exact的含义是强制标注标签必须与类别清单中的名称完全一致从 labelme/_app.py 中的validate_label()实现可以看出它会拿用户输入的标签与已加载的类别集合做精确匹配匹配失败则阻止创建/修改该形状——这是保证转换阶段不出现未知类别异常的第一道防线--config {shape_color: {mode: auto, auto: {shift: -2}}}以 YAML 字符串形式覆盖配置。shape_color.mode: auto表示形状颜色自动分配可选值为auto/uniform/by_label见 labelme/_config/default_config.yamlauto.shift的默认值是0这里设为-2表示在自动生成的颜色序列上做偏移让相邻形状呈现可区分的颜色渐变便于在画布上快速分辨不同标注对象。3.2 按标签规则批量配置标志flagslabelme data_annotated --labels labels.txt --label-flags {.*: [occluded, truncated], person: [male]}--label-flags用于建立标签 → 可选标志列表的映射采用 YAML 格式的正则表达式: [标志...]结构.*: [occluded, truncated]所有形状都可勾选occluded遮挡与truncated截断两个标志person: [male]标签为person的形状额外提供male标志。从 labelme/main.py 的解析实现看该参数既可以是内联 YAML 字符串如本例也可以是 YAML/JSON 文件的路径。标志最终会写入每个 shape 的flags字段虽然不参与掩码生成但可携带重要的属性信息如遮挡、性别、天气等供训练或后处理阶段使用。标注完成后data_annotated目录下每个图片都会生成同名.json文件这就是后续两个转换脚本的输入。四、转换为 VOC 格式数据集4.1 转换命令与输出目录./labelme2voc.py data_annotated data_dataset_voc --labels labels.txt该命令生成如下目录结构data_dataset_voc/ ├── JPEGImages/ # 原图RGB JPEG ├── SegmentationClass/ # 类别标签 PNG ├── SegmentationClassNpy/ # 类别标签 npyint32 数组 ├── SegmentationClassVisualization/ # 类别标签可视化叠加在灰度图上的伪彩色 JPEG ├── SegmentationObject/ # 实例标签 PNG ├── SegmentationObjectNpy/ # 实例标签 npy ├── SegmentationObjectVisualization/ # 实例标签可视化 └── class_names.txt # 写入的类别清单4.2 命令行参数labelme2voc.py 支持三个可选开关参数默认行为作用--noobject生成实例层跳过 SegmentationObject 系列目录--nonpy生成 npy跳过 SegmentationClassNpy / SegmentationObjectNpy--noviz生成可视化跳过 SegmentationClassVisualization / SegmentationObjectVisualization注意输出目录已存在时脚本会直接报错退出Output directory already exists因此重复转换需先清理或更换目录名。4.3 转换原理类别编号与实例合并理解转换结果关键是看懂脚本内部的编号约定见 examples/utils.py 与 labelme2voc.py类别编号从 -1 开始_load_class_names()中class_id i - 1因此__ignore__对应-1、_background_对应0、aeroplane对应1以此类推语义层与实例层分别生成utils.shapes_to_label()对每个形状调用shape_to_mask()栅格化出布尔掩码然后写入两个 int32 数组——cls类别编号与ins实例编号从 1 开始相同(label, group_id)组合共享同一编号即自动合并碎片忽略区域清零ins[cls -1] 0将__ignore__区域的实例值置 0PNG 存 8-bitnpy 存 int32imgviz.io.lblsave()把标签写入 uint8 PNG因此负值-1会被存储为255而 npy 保留原始 int32__ignore__仍为-1实例名按编号命名SegmentationObject的 label_names 为0, 1, 2, ...可视化时每个实例显示其编号转换同时把类别清单写回输出目录的class_names.txt供训练框架直接读取。4.4 标签值约定为什么只有 0、4、14原文档特别提醒查看生成的标签 PNG会发现其中只包含非常低的标签值例如0, 4, 14而255表示__ignore__标签值npy 中为-1。原因在于背景区域占绝大多数值为0画面中实际出现的类别数量很少示例图中只有 person、bottle 等少数类别因此编号4、14这类低值即可覆盖全部前景像素255是 uint8 下对-1的编码用于标记被__ignore__形状圈出的区域训练时通常应将其排除在损失计算之外。4.5 查看标签 PNG../tutorial/draw_label_png.py data_dataset_voc/SegmentationClass/2011_000003.png # 左语义标签 ../tutorial/draw_label_png.py data_dataset_voc/SegmentationObject/2011_000003.png # 右实例标签注原文档中该命令的../tutorial/是相对于examples/instance_segmentation的写法对应的仓库根目录路径为 examples/tutorial/draw_label_png.py。draw_label_png.py 会读取标签 PNG自动把255还原为-1见其中UNLABELED_PNG_VALUE 255的处理逻辑打印标签值分布与标签名映射并用 matplotlib 叠加伪彩色可视化也可通过--image参数同时叠加原图。下图为本示例 VOC 转换输出的三张代表性产物左原始 JPEG中类别标签可视化右实例标签可视化来自 examples/instance_segmentation/data_dataset_voc五、转换为 COCO 格式数据集5.1 转换命令与输出目录./labelme2coco.py data_annotated data_dataset_coco --labels labels.txt该命令生成data_dataset_coco/ ├── JPEGImages/ # 原图RGB JPEG ├── Visualization/ # 实例分割可视化每张图一张 └── annotations.json # COCO 格式标注文件同样地输出目录已存在会直接退出。可选的--noviz参数用于关闭可视化目录的生成。前置依赖该脚本需要pycocotoolslabelme2coco.py 在缺失时会提示pip install pycocotools并退出以及imgviz、numpy。5.2 annotations.json 结构与生成逻辑脚本首先构造 COCO 顶层结构labelme2coco.py 中main()的前半部分{ info: { year: 2026, date_created: 2026-09-20 07:24:57.000000 }, licenses: [{ id: 0, name: null }], type: instances, images: [], categories: [], annotations: [] }各部分的生成规则如下categories同样按class_id i - 1编号__ignore__被跳过不进入类别表_background_为0images每张图一个条目包含file_name相对输出目录的路径、height、width、id按文件排序的自增编号annotations每个实例一个条目包含id、image_id、category_id、segmentation、area、bbox、iscrowd。5.3 形状到 COCO segmentation 的转换细节COCO 的segmentation需要多边形坐标列表脚本对三种常见形状做了专门处理polygon多边形顶点坐标直接展平为[x1, y1, x2, y2, ...]rectangle矩形两个对角点排序后展开为 4 个顶点[x1, y1, x2, y1, x2, y2, x1, y2]circle圆调用_circle_to_polygon_segmentation()做多边形近似——从最少 12 个顶点开始只要弦高误差超过 1 像素容差CIRCLE_APPROXIMATION_TOLERANCE_PX 1.0就翻倍顶点数直至近似误差在 1 像素以内。5.4 实例合并与掩码计算与 VOC 转换一致实例划分同样以(label, group_id)为键group_id为null时生成uuid.uuid1()作为临时分组同一实例的多个形状掩码按位OR合并masks[instance] masks[instance] | mask掩码转为 Fortran 序 uint8 后交给pycocotools.mask.encode()得到 RLE 编码area与bbox也由pycocotools.mask.area()/pycocotools.mask.toBbox()从掩码计算保证面积与包围盒与掩码严格一致iscrowd恒为0。5.5 可视化输出每张图还会生成一张实例可视化Visualization/basename.jpg通过imgviz.instances2rgb()在图上叠加彩色实例掩码、类别标签文字与边框例如 examples/instance_segmentation/data_dataset_coco/Visualization/2011_000003.jpg可用于快速目检标注质量与转换正确性。六、运行前提与依赖标注工具按仓库常规方式安装 labelme 本体后使用labelme命令转换脚本依赖numpy、imgviz、PILVOC 与 COCO 共用COCO 转换额外需要pycocotoolsexamples/utils.py 是自包含的 JSON 标注读取与栅格化工具其模块注释明确指出它刻意不依赖 labelme 包本身只依赖标准库、numpy 与 PIL——这既是本示例的工作参考实现也可以直接复制到你自己的数据加载代码中例如 PyTorch 的Dataset无论 labelme 内部如何演进都能稳定工作。七、总结从本示例可以提炼出一条完整的实例分割数据生产流水线用labels.txt定义类别含__ignore__、_background_两个特殊条目用labelme配合--validate-label exact与--label-flags完成高质量标注注意通过group_id表达同一实例的多个碎片用 labelme2voc.py 输出 VOC 格式JPEGImages SegmentationClass/Object 的 PNG/npy/可视化供语义与实例分割模型使用用 labelme2coco.py 输出 COCO 格式JPEGImages annotations.json供基于 COCO API 的检测/分割框架直接消费最后用 draw_label_png.py 或Visualization目录核对标签值与实例划分是否符合预期。理解class_id i - 1、255 -1ignore以及(label, group_id)实例合并这三条核心约定你就能完全掌握 labelme 实例分割数据在 VOC 与 COCO 两大生态之间的自由转换。【免费下载链接】labelmeImage annotation with Python. Supports polygon, rectangle, circle, line, point, and AI-assisted annotation.项目地址: https://gitcode.com/gh_mirrors/la/labelme创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考