news 2026/9/21 2:43:13

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
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.pylabelme2coco.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.jpg2011_000006.jpg2011_000025.jpg三张示例图片及其同名.json标注文件;data_dataset_vocdata_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 中记为255(npy 中为-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,说明它们是同一个人的两块多边形碎片,转换时会被合并为一个实例;而第三个persongroup_idnull,会作为独立实例处理。__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.yaml),auto.shift的默认值是0,这里设为-2表示在自动生成的颜色序列上做偏移,让相邻形状呈现可区分的颜色渐变,便于在画布上快速分辨不同标注对象。

3.2 按标签规则批量配置标志(flags)

labelme 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/ # 类别标签 npy(int32 数组) ├── 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. 类别编号从 -1 开始_load_class_names()class_id = i - 1,因此__ignore__对应-1_background_对应0aeroplane对应1,以此类推;
  2. 语义层与实例层分别生成utils.shapes_to_label()对每个形状调用shape_to_mask()栅格化出布尔掩码,然后写入两个 int32 数组——cls(类别编号)与ins(实例编号,从 1 开始,相同(label, group_id)组合共享同一编号,即自动合并碎片);
  3. 忽略区域清零ins[cls == -1] = 0__ignore__区域的实例值置 0;
  4. PNG 存 8-bit,npy 存 int32imgviz.io.lblsave()把标签写入 uint8 PNG,因此负值(-1)会被存储为255;而 npy 保留原始 int32,__ignore__仍为-1
  5. 实例名按编号命名SegmentationObject的 label_names 为0, 1, 2, ...,可视化时每个实例显示其编号;
  6. 转换同时把类别清单写回输出目录的class_names.txt,供训练框架直接读取。

4.4 标签值约定:为什么只有 0、4、14

原文档特别提醒:查看生成的标签 PNG,会发现其中只包含非常低的标签值(例如0, 4, 14),而255表示__ignore__标签值(npy 中为-1)。原因在于:

  • 背景区域占绝大多数,值为0
  • 画面中实际出现的类别数量很少(示例图中只有 person、bottle 等少数类别),因此编号414这类低值即可覆盖全部前景像素;
  • 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参数用于关闭可视化目录的生成。前置依赖:该脚本需要pycocotools(labelme2coco.py 在缺失时会提示pip install pycocotools并退出),以及imgviznumpy

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_0
  • images:每张图一个条目,包含file_name(相对输出目录的路径)、heightwidthid(按文件排序的自增编号);
  • annotations:每个实例一个条目,包含idimage_idcategory_idsegmentationareabboxiscrowd

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_idnull时生成uuid.uuid1()作为临时分组;
  • 同一实例的多个形状掩码按位OR合并(masks[instance] = masks[instance] | mask);
  • 掩码转为 Fortran 序 uint8 后交给pycocotools.mask.encode()得到 RLE 编码,areabbox也由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命令;
  • 转换脚本依赖:numpyimgvizPIL(VOC 与 COCO 共用),COCO 转换额外需要pycocotools
  • examples/utils.py 是自包含的 JSON 标注读取与栅格化工具,其模块注释明确指出它刻意不依赖 labelme 包本身,只依赖标准库、numpy 与 PIL——这既是本示例的工作参考实现,也可以直接复制到你自己的数据加载代码中(例如 PyTorch 的Dataset),无论 labelme 内部如何演进都能稳定工作。

七、总结

从本示例可以提炼出一条完整的实例分割数据生产流水线:

  1. labels.txt定义类别(含__ignore___background_两个特殊条目);
  2. labelme配合--validate-label exact--label-flags完成高质量标注,注意通过group_id表达"同一实例的多个碎片";
  3. 用 labelme2voc.py 输出 VOC 格式(JPEGImages + SegmentationClass/Object 的 PNG/npy/可视化),供语义与实例分割模型使用;
  4. 用 labelme2coco.py 输出 COCO 格式(JPEGImages + annotations.json),供基于 COCO API 的检测/分割框架直接消费;
  5. 最后用 draw_label_png.py 或Visualization目录核对标签值与实例划分是否符合预期。

理解class_id = i - 1255 = -1(ignore)以及(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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/21 2:41:39

视频会议系统操作手册:从结构设计到doc格式落地全攻略

简介&#xff1a;《视频会议系统操作手册》是一份面向企业、教育机构、政府机关等组织的视频会议管理员及日常使用者的实用文档&#xff0c;旨在帮助用户系统掌握视频会议前、中、后的操作要点&#xff0c;减少因配置不当或操作失误导致的网络丢包、音画不同步等问题。资源包内…

作者头像 李华
网站建设 2026/9/21 2:41:03

Apache APISIX jwe-decrypt 插件实战:JWE 令牌解密与明文透传指南

Apache APISIX jwe-decrypt 插件实战&#xff1a;JWE 令牌解密与明文透传指南 【免费下载链接】apisix The Cloud-Native API Gateway and AI Gateway 项目地址: https://gitcode.com/gh_mirrors/api/apisix jwe-decrypt 是 Apache APISIX 内置的认证&#xff08;auth&a…

作者头像 李华
网站建设 2026/9/21 2:39:58

OpenClaw 安装方法补一步:模型通道改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 2:37:54

STM32CubeMX安装深度指南:嵌入式AI编程的基座构建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/21 2:35:19

Sails 应用优雅关闭指南:sails.lower() 方法深度解析

Sails 应用优雅关闭指南&#xff1a;sails.lower() 方法深度解析 【免费下载链接】sails Realtime MVC Framework for Node.js 项目地址: https://gitcode.com/gh_mirrors/sa/sails lower() 是 Sails 生命周期中与 lift() 对应的逆操作&#xff1a;它会关闭已启动的应用…

作者头像 李华