- 数据标注
- 计算机视觉
- 桌面应用
【免费下载链接】labelme
Image annotation with Python. Supports polygon, rectangle, circle, line, point, and AI-assisted annotation.
导读
图像分类标注不需要画框、画多边形,只需要为整张图片打上一个类别标签(例如“cat”“dog”)。本文以 labelme 仓库中的 classification 示例 为骨架,完整讲解如何用 labelme 的--flags机制完成图像级分类标注:从flags.txt的编写、命令行启动,到 JSON 标注文件的解析、GUI 交互行为,再到与实例分割等形状标注流程的差异与进阶用法(正则驱动的--label-flags动态规则)。读完本文,你将掌握一套可复制、可运行的图像分类标注工作流,并能理解其底层实现原理。
一、示例概览:用 Flags 表达图像级类别
在 examples/classification 目录下,官方提供了最简化的分类标注示例:
flags.txt:声明可用的类别标签(flag)列表;data_annotated/0001.jpg与0001.json:一张猫图片及其标注结果(flagcat: true);data_annotated/0002.jpg与0002.json:一张狗图片及其标注结果(flagdog: true)。
与实例分割示例(examples/instance_segmentation)不同,分类示例的 JSON 中shapes为空数组——不标注任何几何形状,类别信息全部存放在flags字段中。这正是“图像分类”与“目标检测 / 实例分割”在标注层面的本质区别:前者给整张图打标签,后者给图中的每个目标画形状。
二、启动命令与 flags.txt 的编写
官方 README 给出的启动命令只有一行:
labelme data_annotated --flags flags.txt其中data_annotated是待标注图片目录,--flags flags.txt指定类别定义文件。示例中的 flags.txt 内容如下:
__ignore__ cat dog每行一个 flag 名。第一行__ignore__是保留项:勾选后表示“跳过/忽略”该图,不参与分类,常用于过滤质量不合格的样本。后面每一行就是一个候选类别,例如cat、dog。类别名称支持任意自定义字符串(如bus、person、defect_ok),实际使用中可按业务命名。
--flags 参数解析规则(源码级验证)
--flags参数在 labelme/main.py 中定义,帮助信息写明其接受两种形式:
- 逗号分隔列表:如
--flags "cat,dog"; - 文件路径:每行一个 flag,如
--flags flags.txt。
具体解析由_parse_list_arg完成(labelme/main.py):
def _parse_list_arg(value: str, /) -> list[str]: if os.path.isfile(value): with open(value, encoding="utf-8") as f: return [line.strip() for line in f if line.strip()] return [line.strip() for line in value.split(",") if line.strip()]可以看到,当参数值是一个存在的文件时按行读取、自动去除首尾空白与空行;否则按逗号切分。因此两种写法的效果等价:
# 写法一:文件 labelme data_annotated --flags flags.txt # 写法二:内联逗号列表 labelme data_annotated --flags "cat,dog"三、标注结果解析:JSON 中的 flags 字段
完成标注并保存后,每张图对应一个 JSON 文件。示例中 0001.json 的完整内容为:
{ "version": "4.0.0", "flags": { "__ignore__": false, "cat": true, "dog": false }, "shapes": [], "imagePath": "0001.jpg", "imageData": null, "imageHeight": 480, "imageWidth": 640 }0002.json 则对应dog: true, cat: false。逐字段说明:
| 字段 | 含义 | 分类示例中的取值 |
|---|---|---|
version | 标注文件格式版本 | 4.0.0 |
flags | 图像级布尔标志字典 | 勾选的类别为true,其余为false |
shapes | 形状标注列表(点、矩形、多边形等) | [],分类标注不画形状 |
imagePath | 关联的图片文件名 | 0001.jpg |
imageData | 内嵌图片 base64 数据(默认null) | null |
imageHeight/imageWidth | 图片像素尺寸 | 480/640 |
flags字段的语义是**“本图属于哪些类别”**:分类任务通常只勾选一个(互斥),但机制本身支持多选(如cat: true, dog: true表示图中同时存在猫和狗)。下游训练代码只需解析flags字典中值为true的键,即可得到该图的类别标签。若未安装 labelme CLI 环境,也可直接用 Python 读取:
import json with open("data_annotated/0001.json", encoding="utf-8") as f: data = json.load(f) labels = [k for k, v in data["flags"].items() if v] print(labels) # ['cat']四、GUI 中的 Flags 交互行为
启动后,labelme 会在标注界面中为flags.txt里的每个 flag 渲染一个复选框(checkbox),位置位于标签输入对话框(Label Dialog)区域。其底层实现在 labelme/_widgets/_label_dialog.py:
- 对话框初始化时通过
compile_label_flags编译 flags 规格(labelme/_widgets/_label_dialog.py); - 用户在文本框中输入类别名时,
_update_flags会按当前文本动态刷新复选框(labelme/_widgets/_label_dialog.py); - 每个复选框对应一个布尔状态,确认后写入 shape / 图像级
flags字典。
注意一个细节:分类标注中即使不输入任何 label 文本,仅勾选cat复选框同样能提交一条有效标注(labelme/_widgets/_label_dialog.py 的 OK 按钮启用逻辑只要求“label 被锁定或文本框非空”,而分类场景下类别信息由 flags 承载)。这也是示例中 JSON 的shapes为空、类别全在flags里的原因。
五、与形状标注(实例分割)流程的区别
将分类示例与 examples/instance_segmentation/README.md 对比,可以清晰看到两种标注范式的差异:
| 维度 | 分类标注 | 实例分割标注 |
|---|---|---|
| 标注单位 | 整张图片 | 图中每个目标对象 |
| 标注方式 | 勾选 flags 复选框 | 绘制多边形 / 矩形等形状 |
| 类别载体 | JSON 的flags字段 | 每个 shape 的label字段 |
shapes内容 | 空数组[] | 一个或多个形状定义 |
| 典型下游任务 | 图像分类(CNN 分类器) | 目标检测、分割(如 labelme2voc / labelme2coco 转换) |
分类任务中一个 shape 都没有,因此不需要在画布上做任何几何操作,只需为每张图片勾选类别并保存,标注速度非常快。
六、进阶:正则驱动的动态 Flags(--label-flags)
--flags提供的是全局固定的候选类别列表;而 labelme 还提供--label-flags参数,让 flag 集合随标签名动态变化。该参数同样定义在 labelme/main.py,接受内联 YAML 映射或 YAML/JSON 文件,键为正则表达式、值为该正则匹配的标签应显示的 flag 列表,例如:
labelme data_annotated \ --label-flags '{person-\d+: [male, tall], dog-\d+: [black, brown, white], .*: [occluded]}'其核心实现位于 labelme/_label_flags.py:
compile_label_flags将键编译为正则对象,并对非法模式做容错——非字符串键、无法编译的正则(如cat()会被记录警告后跳过,保证应用不因用户配置错误而崩溃(labelme/_label_flags.py);get_default_flags根据当前标签名匹配到的正则,返回对应的默认 flag 字典(labelme/_label_flags.py);apply_default_flags在加载标注时为每个 shape 应用默认 flags(labelme/_label_flags.py)。
该行为有专门单元测试覆盖,见 tests/unit/_label_flags_test.py:例如{"^cat$": ["occluded", "truncated"]}会为标签cat生成{"occluded": False, "truncated": False}的默认复选框;而非法模式(如cat(、非字符串键2024、bytes 键)会被静默丢弃(tests/unit/_label_flags_test.py)。
对纯分类场景,
--flags已足够;--label-flags更适合目标检测 / 实例分割中“同一类目标拥有不同属性”(如行人性别、车辆颜色、遮挡与否)的细粒度标注。
七、配置文件中的 flags 项
除了命令行参数,flags与label_flags也出现在用户配置文件(默认~/.labelmerc,可通过--config覆盖)中,见 labelme/_config/default_config.yaml:
flags: # 全局 flag 列表,等价于 --flags label_flags: # 标签正则 -> flag 列表,等价于 --label-flags命令行参数会作为配置覆盖项与配置文件合并(labelme/main.py),因此两种配置途径可以混用:把团队共用的类别写进配置文件,把临时类别通过--flags内联传入。关于配置架构的完整设计可参考 docs/adr/0001-settings-architecture.md。
八、完整实战流程
下面是一条端到端的分类标注流水线:
准备图片目录:将待分类图片放入一个目录,例如
data_annotated/;编写 flags.txt:首行保留
__ignore__,后续每行一个类别:__ignore__ cat dog启动标注:
labelme data_annotated --flags flags.txt逐图勾选类别:为每张图片勾选正确的类别复选框,
__ignore__用于剔除无效样本,然后保存(默认自动保存,可在配置中通过auto_save控制,见 labelme/_config/default_config.yaml);导出标注:遍历目录下所有
*.json,读取flags中为true的键作为类别标签,组装成训练数据集(如{image_path: label}的 CSV 或 TFRecord),供下游分类模型使用。
九、小结
图像分类标注在 labelme 中是一个“轻量”但完整的流程:通过--flags(或配置文件中的flags项)声明类别候选,GUI 中勾选复选框写入 JSON 的flags字段,shapes保持为空,下游按布尔值为true的键读取类别。其底层由 labelme/_label_flags.py 的编译、匹配、应用三段式实现支撑,并配有单元测试与官方示例(examples/classification),无论是快速标注实验数据,还是搭建正式的分类数据集生产管线,都可以直接参考本文流程落地。
- 数据标注
- 计算机视觉
- 桌面应用
【免费下载链接】labelme
Image annotation with Python. Supports polygon, rectangle, circle, line, point, and AI-assisted annotation.
相关推荐
基于Labelme和ResNet的图像分类实战指南:从标注到智能识别
还在为图像数据集标注耗费大量时间?标注好的数据不知道怎么用于模型训练?别担心,今天我就带你用Labelme标注工具和ResNet深度学习模型,从零开始打造一个图
数据标注计算机视觉桌面应用10分钟搞定图像标注与分类:Labelme+ResNet实战指南
10分钟搞定图像标注与分类:Labelme+ResNet实战指南 你还在为数据集标注耗费大量时间?标注好的数据不知道如何用于训练?本文将带你使用Labelme(
数据标注计算机视觉桌面应用零基础到实战:Labelme图像标注+ResNet分类全流程解密
还在为图像分类项目的数据准备头疼吗?🤔 手动标注几百张图片、整理数据格式、训练模型……每个环节都可能让你抓狂。别担心,今天就用最接地气的方式,带你从零开始构建
数据标注计算机视觉桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考