先交代一下背景。做计算机视觉项目,不管你是搞目标检测、语义分割还是实例分割,永远绕不开数据标注这一步。而 Labelme 作为一款开源图像标注工具,在 Windows 系统下的安装和使用可以说是每个新手必过的一道坎。我见过太多人在第一步就卡住:要么 PyQt5 装不上,要么装上了不知道怎么画多边形,要么标完一堆 JSON 文件却不知道下一步该怎么办。这篇文章我会把从零开始的完整流程拆开揉碎,逐步演示安装、启动、标注和格式转换,帮你在 Windows 下把整个标注链路彻底跑通。
文章面向刚接触图像标注的算法工程师、数据标注新人,也适合准备做语义分割或实例分割项目、想自己生成训练数据集的读者。按照我平时做项目实际走的顺序来写,尽量把每一步背后的原理和注意事项也讲清楚,不希望你只是照着命令敲一遍。
1. 项目背景与整体思路:为什么数据标注绕不开 Labelme
1.1 Labelme 是什么,能解决什么问题
Labelme 是基于 Python 开发的开源图像标注工具,最初由麻省理工学院的计算机科学和人工智能实验室发布。它最核心的能力是支持多边形标注,也就是你可以沿着目标物体边缘打点,闭合后得到一个不规则区域,正好对应语义分割和实例分割任务里的像素级标注需求。以前大家做目标检测,用 LabelImg 画矩形框就足够了,但一旦模型需要输出轮廓、区分每一个实例,矩形框就远远不够,Labelme 的多边形标注能力恰好填补这个缺口。
除了多边形,它还支持矩形框、圆形、线条、点以及图像分类标签。换句话说,从目标检测到关键点检测、从边缘分割到图像分类,一个工具基本都能覆盖。我平时做工业质检、遥感地物识别、医学影像辅助诊断这类项目时,第一步永远是把图像整理好,然后用 Labelme 按类别打标签。它输出的 JSON 格式也相当友好,每个文件对应一张图的标注信息,方便后续写脚本转成 VOC、COCO 或自定义数据集格式。
1.2 为什么我推荐新手从 Labelme 开始
我试过不少标注工具,有的界面确实漂亮但安装过程太折腾,有的功能很强但输出格式封闭,还有的商业软件核心功能要收费。相比之下,Labelme 有几个对新手非常友好的点:第一,完全开源,代码和依赖都透明,装坏了随时重建环境;第二,跨平台,Windows、macOS、Linux 都能跑;第三,交互逻辑简洁,主流程就是打开文件夹、选标签、画点、保存、下一张,没有太多复杂概念;第四,背靠 Python 生态,安装一条命令就能完成,后续做格式转换和批量处理也顺手。
当然它也有不足,比如超大尺寸图像打开时会卡顿、没有云协作功能、多变形只能逐张手工标注。但这些问题通常不影响小规模项目和个人学习使用。对于刚入门的读者,先用 Labelme 把图像标注、数据整理、喂给模型这条链路跑通,比一开始就折腾企业级标注平台要实际得多。
1.3 整体安装与实操路线图
这篇文章不会只给你一两条命令就结束。整个流程我拆成四个阶段:环境准备、安装验证、界面实操、数据转换。先装 Anaconda 并创建独立环境,再通过 pip 安装 Labelme,然后启动界面认识各个功能区,接着用一组图片走完标注全流程,最后讲怎么把 JSON 转换到模型常用的格式,并附上常见问题排查表。每一步我都会解释原因,比如环境隔离的用意、PyQt5 和 Python 版本的对应关系、标签文件为什么要放在指定位置等。
走完这一遍之后,你会发现自己不仅会“用”这个工具,还对标注数据的结构有了系统认识。后面无论换到其他标注软件,还是自己写数据增广脚本,都能更快上手。
2. 环境准备:先把 Python 运行环境安排明白
2.1 Python 版本怎么选,直接用系统 Python 行不行
Labelme 是 Python 应用,所以电脑上必须先有 Python 环境。理论上,直接去 python.org 下载一个 Python 3.8 或 3.9 安装包也能用,但我不建议新手这么干。主要原因有两个:一是 Labelme 依赖 PyQt5、numpy、pillow 等一堆第三方库,如果直接装在系统 Python 里,很容易跟其他项目产生依赖冲突;二是以后你大概率还会装 PyTorch、TensorFlow、OpenCV 这些库,不同项目对 Python 版本的要求不一样,环境乱了会很难收场。
我平时推荐安装 Anaconda,它自带 Python 解释器、conda 包管理器和很多常用科学计算库。Anaconda 安装包体积比较大,初次安装可能需要几分钟,但胜在省心。如果磁盘空间有限或者只想要轻量方案,可以装 Miniconda,只保留 conda 和 Python 基础部分,Labelme 的依赖全部交给 pip 解决。我自己在 Windows 上用的就是 Anaconda,后续不管是建新环境还是切换 Python 版本都非常方便。
2.2 Anaconda 在 Windows 上的安装细节
去官网下载 Anaconda 最新版安装包时,尽量选择 64 位 Windows 版本。安装过程中有几个选项容易被忽略,我这里专门提醒一句:在 Advanced Installation Options 页面,它会问是否把 Anaconda 添加到 PATH 环境变量,建议不要勾选。因为 conda 自带的 Python 版本一旦接管系统命令,可能会影响其他软件的 Python 调用。安装完成后,我们通过“Anaconda Prompt”这个专用终端进入环境,就不需要手动配置 PATH 了。
安装好之后先验证一下环境。打开 Anaconda Prompt,依次输入python --version和conda --version,能看到版本信息就说明基础环境没问题。如果提示找不到命令,多半是安装过程被安全软件拦截,或者安装路径带了中文字符。卸载重装到纯英文路径,一般情况下都能解决。
2.3 创建独立的 labelme 工作环境
接下来是很多人忽略但非常关键的一步:为 Labelme 单独建一个虚拟环境。我习惯在 Anaconda Prompt 里先看一眼当前有哪些环境,输入conda env list,然后执行:
conda create -n labelme python=3.8 -y这里的labelme是环境名称,可以自己改,比如label_env、annotate都行。指定python=3.8是因为这个版本跟 PyQt5、Labelme 近期版本配合得比较稳。虽然 Python 3.10、3.11 也能装,但个别 Windows 机器上会出现 PyQt5 编译组件缺失的问题,没必要冒险。
创建完成后激活环境:
conda activate labelme激活后终端前面会出现(labelme)字样,表示当前已经进入独立环境。此后所有安装和启动操作都在这个环境里进行。这样做最大的好处是,哪怕 Labelme 把依赖库搞乱,也不会污染系统里其他项目的 Python 环境;反过来,其他项目升级 numpy、opencv,也不会影响标注工具的运行。
3. 正式安装与首次启动:从命令行到图形界面
3.1 用 pip 安装 Labelme
环境激活后,接下来就进入正题了。在 Anaconda Prompt 里执行:
pip install labelme如果只想安装指定版本,可以带上版本号,比如pip install labelme==5.1.1。我遇到过不少朋友反馈说直接安装最新版会有界面小问题,我本人用下来 5.x 版本都还算稳定,4.x 的 JSON 输出结构跟新版略有差异,如果你的项目代码已经适配了旧版,就按实际需求固定版本安装。
安装过程会拉取 PyQt5、opencv-python、numpy、pillow 等依赖,网速正常的话一般几分钟内完成。这里说一个提高成功率的小技巧:如果安装时卡在下载大文件,可以考虑给 pip 配置国内镜像源,比如清华源、阿里源,在命令行后面加-i https://pypi.tuna.tsinghua.edu.cn/simple即可。这只是一个网络优化选项,不影响任何功能。
3.2 验证安装结果
安装完成后,先验证一下版本号:
labelme --version能输出版本号,说明程序主体已经安装成功。接下来你想直接启动图形界面也行,但我建议先做一个小检查,确认图形依赖没问题。在命令行输入:
python -c "from PyQt5.QtWidgets import QApplication; print('PyQt5 OK')"如果输出PyQt5 OK,说明 PyQt5 图形库正常,可以放心启动界面。如果这一步报错,多半是 PyQt5 没装好,重新执行pip install pyqt5就可以。
3.3 启动界面与整体布局
在 Anaconda Prompt 中激活labelme环境后,直接输入:
labelme界面会弹出来,默认是一个主窗口,顶部是菜单栏和工具栏,左侧是待标注文件列表,中间是图像显示区域,底部显示当前鼠标位置和图像信息。第一次打开时你会发现“下一步”“保存”等按钮都处于灰色不可用状态,因为还没打开任何图片。这时候不要着急,先按 3.4 节准备好标签文件,再打开图片目录,工具栏就会被激活。
3.4 准备标签文件 label.txt
Labelme 在打开图片前,最好先准备好一个标签列表文件,它是一份纯文本文件,每一行写一个类别名称。比如你要做猫狗分割,就建一个label.txt,内容为:
cat dog保存到任意容易找到的位置。然后在 Labelme 菜单栏选择打开目录 Open Dir,选中你存放图片的文件夹,再把编辑 Edit 菜单里的标签列表指向这个label.txt。这样做的好处有两个:一是标注时可以直接从下拉列表选类别,不用每次手敲;二是避免同一个类在不同图片里出现“猫”“Cat”“mao”这种命名不一致的情况。很多标注事故最后排查发现,就是标签名不统一,导致模型训练时把同一个类拆成了多个类。
3.5 打开图片目录的几种方式
Labelme 支持两种打开方式:打开单张图片 Open File 和打开整个目录 Open Dir。只修一两张图,用 Open File 就行;正式标注一个数据集,我强烈建议把图片统一放到一个文件夹,用 Open Dir 批量管理。点击“打开目录”后,左侧文件列表会显示文件夹下所有支持的图片格式,常见格式包括.jpg、.png、.bmp,右侧主区域显示当前图片,下方有上一张、下一张切换按钮。
需要注意图片文件夹里最好不要混入其他无关文件,比如 Excel 表格、隐藏的 Thumbs.db。Labelme 虽然会按扩展名过滤,但文件夹太乱会让你切换图片时心里没底。还有一个细节,项目路径最好不要带中文和特殊符号,Windows 下出现过因为中文路径导致 JSON 里imagePath记录异常的情况,尽量用英文路径最稳妥。
4. Labelme 实操全流程:从画出第一个多边形到保存 JSON
4.1 选择标签类别与创建多边形
打开图片目录后,界面上工具栏的“创建多边形” Create Polygons 按钮就会亮起来。点击它,鼠标会变成十字光标,接下来就是标注的核心操作:沿着目标物体边缘,用鼠标左键逐个打点。每单击一次,就生成一个多边形顶点;双击鼠标左键,多边形闭合,弹出标签选择框,选中对应类别后回车确认。
第一次用多边形标注的人容易犯点打得太密的错误。如果图像里物体轮廓很简单,比如一个矩形的包装盒,四五个点就够了,没必要每隔几个像素打一个点。顶点少,后面调整和导出的轮廓数据更干净;顶点特别多,不仅保存的 JSON 文件变大,模型训练时对轮廓起止点捕捉的难度也会增加。当然,如果物体形状确实复杂,比如叶片边缘、遥感建筑轮廓,该加的点还是要加,保证贴着真实边缘走。
4.2 编辑已有标注:调整顶点、移动与撤销
标注过程中经常要修改。Labelme 的“编辑多边形” Edit Polygons 功能可以让你调整已经画好的标注。点击左侧工具栏的编辑图标后,每个已存在多边形的角点会变成红色小方框,你可以按住某个角点拖动来调整位置,也可以直接拖动某条边来改变整体位置。对标签类别标错的对象,右键菜单里有“删除多边形” Delete Polygon 选项;对误操作产生的点,可以用 Ctrl+Z 撤销最近一步。
我个人的习惯是先粗标一遍,把明显轮廓打出来,再切换到编辑模式,放大图像细调边缘点。这样比一边打点一边反复改更高效。另外,如果多张图里同一个物体的位置和大小都非常接近,Labelme 没有直接复制标注到下一张图的功能,但你可以通过复制一份 JSON 文件、手动改imagePath字段,再在下一张图里用编辑功能把标注拖到新位置,这算是老手才会用的小技巧。
4.3 三种经常会用到的标注方式:矩形、圆形与线条
除了多边形,Labelme 工具栏里还有创建矩形 Create Rectangle、创建圆 Create Circle、创建线条 Create Line 和创建点 Create Point。矩形框主要用在目标检测场景,画的时候从左上角拖到右下角,松开鼠标,弹窗选类别即可。生成的 JSON 里shape_type是rectangle,坐标是左上角和右下角两个点,后续写脚本转成 YOLO 格式时,只需要计算中心点和宽高。
圆形在标注圆形物体、球体、细胞核等场景比较常用,只需要确定圆心和半径,先单击圆心,再单击圆周上一点,就完成一个圆。线条和点则适合做关键点检测或者车道线、骨架线这类任务。这里特别提醒一句:不同标注类型的shape_type字段不一样,如果你的模型只认多边形或矩形,那么转换脚本里要分清shape_type再做相应换算,否则会出现“画好了但训练代码读取不了”的尴尬。
4.4 保存标注结果与 JSON 文件结构详解
画完一张图后,按 Ctrl+S 或点击“保存”按钮,Labelme 会为该图片生成一个同名但扩展名为.json的文件,存放在图片同级目录下。打开这个 JSON,你会发现几个核心字段:
version:当前 Labelme 版本信息,5.x 版本会对格式做少量兼容处理。imagePath:原始图片的相对路径,通常就是不带目录的图片文件名。imageData:图片的 Base64 编码。如果该字段不为空,那么即使图片被单独拿走,拿着 JSON 也能还原整张图;但这会显著增大文件体积。shapes:一个数组,包含这张图上所有标注对象,每个对象里有label(类别名)、points(坐标点数组)、shape_type(标注类型)、group_id(分组 ID)等字段。imageWidth和imageHeight:原图宽高,写转换脚本时可以直接用这两个字段校验坐标是否越界。
很多人第一次看到imageData里很长一串 Base64 字符就觉得文件很“脏”,其实它是把整张图片编码进了 JSON。Labelme 默认会包含这个字段,但如果你的数据集图片已经单独存放,建议转换时把imageData置空,节省存储空间。
4.5 批量切换图片时的高效习惯
标注一两张图很轻松,但几百张就很考验效率。我总结下来的高效习惯是:把图片按类别和场景分好文件夹,每个文件夹内放一个label.txt,打开目录后按 A 键切换到上一张、D 键切换到下一张;标注完一张立刻 Ctrl+S 保存,然后再切下一张。不要等到最后统一保存,万一中途软件崩溃或者电脑断电,在没有自动保存的情况下,所有劳动都可能白费。
另外,我建议每标完 50 张左右,手动检查一下生成的 JSON 文件数量和图片数量是否一致,顺手用文本编辑器抽查几个 JSON,确认label字段没有空值、points不为空。小批量抽查的成本很低,但能提前发现类别名拼写错误、漏标这种问题,避免全部标完再返工。
5. 数据转换:把 JSON 变成模型训练需要的格式
5.1 为什么不能直接把 JSON 丢给模型
深度学习框架和数据加载器一般不会直接吃 Labelme 的 JSON,最常用的数据格式是 VOC 格式(XML 标注)、COCO 格式(JSON 标注)以及 YOLO 格式(TXT 标注)。所以要经过一步“数据转换”。这一步对纯手工标注项目来说几乎是必须的,因为你自己定制的数据加载器很可能按 VOC 或 COCO 的规范来写。哪怕模型加载逻辑是自己写的,也应该把标注数据统一成固定模板,方便后续做数据增强和划分训练集。
5.2 JSON 转 COCO 格式的参考脚本
我这里放一个结构简单的 Python 转换脚本,它会把某个文件夹下的所有 Labelme JSON 汇总成一个 COCO 格式的 JSON。注意这里只处理shape_type为polygon的标注,如果你画的是矩形框,需要额外处理成bbox。
import json import os import glob def labelme_to_coco(img_dir, output_path): images = [] annotations = [] categories = {} ann_id = 1 img_id = 1 for json_path in glob.glob(os.path.join(img_dir, "*.json")): with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) image_name = data["imagePath"] width = data.get("imageWidth", 0) height = data.get("imageHeight", 0) images.append({ "id": img_id, "file_name": image_name, "width": width, "height": height }) for shape in data["shapes"]: label = shape["label"] if label not in categories: categories[label] = len(categories) + 1 cat_id = categories[label] points = shape["points"] xs = [p[0] for p in points] ys = [p[1] for p in points] seg = [] for i in range(len(points)): seg.extend([points[i][0], points[i][1]]) x_min = min(xs) y_min = min(ys) w = max(xs) - min(xs) h = max(ys) - min(ys) annotations.append({ "id": ann_id, "image_id": img_id, "category_id": cat_id, "segmentation": [seg], "area": w * h, "bbox": [x_min, y_min, w, h], "iscrowd": 0 }) ann_id += 1 img_id += 1 coco_categories = [{"id": v, "name": k} for k, v in categories.items()] coco = { "images": images, "annotations": annotations, "categories": coco_categories } with open(output_path, "w", encoding="utf-8") as f: json.dump(coco, f, ensure_ascii=False, indent=2) if __name__ == "__main__": labelme_to_coco("./images", "./coco_output.json")这个脚本比较基础,核心逻辑是把每张图的shapes铺展开:多边形坐标拉成一维数组,最小外接矩形的左上角坐标和宽高作为bbox,类别从 1 开始自动编号。实际项目里可能需要额外处理group_id、多实例 ID 等逻辑,你可以按需扩展。
5.3 转成 VOC XML 的思路
COCO 格式适合用pycocotools评估的数据集,但很多老项目还是用 VOC 格式。VOC 格式本质上是一个 XML 文件,里面列出size、object、bndbox、polygon等节点。Labelme 官方仓库里其实提供了一个脚本labelme2voc.py,在 GitHub 的examples目录下,会把标注转成 PASCAL VOC 目录结构,同时生成JPEGImages、Annotations、SegmentationClass、SegmentationObject等文件夹,方便直接喂给分割模型。
如果不想用官方脚本,也可以自己写,但本质上就是把 JSON 解析成 XML 字符串。相比 COCO 转换,VOC 的 XML 会多一个<difficult>0</difficult>字段,表示该目标是否难以识别,一般我们都会置为 0。另外提醒一下,VOC 格式对文件名有严格要求,一般是000001.jpg、000002.jpg这样的六位数字编号,如果图片文件名是中文或者带空格,要先重命名。
5.4 标注数据检查和清洗
转换完成后,我还会做一轮数据检查。最简单的方法是写个脚本,把所有图片的尺寸读出来,跟 JSON 里的imageWidth、imageHeight比对,如果发现大量不一致,多半是图片在标注后被压缩或者替换过,需要重新标注。另外,也可以把 JSON 里的points坐标画回图像上,生成一张带标注的预览图,人工扫一眼确认多边形位置基本合理,这样能避免“标注了,但转出来坐标全飞了”的坑。
6. 常见问题排查与避坑指南
6.1 安装或启动时遇到依赖报错
我在 Windows 上踩过比较多的坑是ModuleNotFoundError: No module named 'PyQt5'。这种情况一般出现在 pip 安装时网络中断,或者 PyQt5 没被自动安装上。解决方法是重新执行pip install pyqt5,装完再启动。还有一种情况是ImportError: DLL load failed,通常是 Python 环境里存在多个 OpenCV 或 numpy 版本冲突,可以将环境里的相关包升级到最新版,或者干脆删除环境重建。
conda remove -n labelme --all conda create -n labelme python=3.8 -y pip install labelme这条组合拳能解决 80% 的“玄学报错”。很多时候我不想花时间排查依赖版本之间的复杂问题,直接重建干净环境反而最快,这也是我前面反复强调环境隔离最主要的原因。
6.2 打开界面后工具栏灰色、无法标注
如果打开目录后发现“创建多边形”按钮依然是灰色,通常有三个原因:一是标签列表没设置,软件要求先知道有哪些类别,你可以在编辑菜单的标签列表里指向label.txt,或者直接在标注时手动输入;二是当前查看的图片格式不受支持,虽然常见格式都能打开,但个别 PNG 文件如果用了特殊色彩通道,也可能出问题;三是窗口太小,工具栏按钮被折叠到菜单里了,这是 Windows 下高分屏适配不佳导致的,把窗口拉大一点或者调整分辨率就能解决。
6.3 Python 环境变量和命令行找不到 labelme
有朋友反映,在 cmd 里输入labelme提示不是内部或外部命令,但在 Anaconda Prompt 里就正常。原因是他们没有激活labelme环境,当前 cmd 会话用的是系统 Python。Windows 的终端环境是会话级的,每次打开新窗口后都要重新执行conda activate labelme,不要以为之前激活过就一直有效。如果不想每次都敲这行命令,可以在 Anaconda Prompt 里激活后直接输入python -m labelme来启动,不过这只是绕过问题,治本的办法还是理解 conda 环境生命周期。
6.4 标注时鼠标错位、界面卡顿、图像模糊
高分屏和缩放比例非 100% 的 Windows 设备上,Labelme 可能出现鼠标光标与图像上实际落点位置不一致的问题。这个问题根源是 Qt 在高 DPI 缩放下的坐标映射。如果遇到,可以在启动前设置环境变量:
set QT_AUTO_SCREEN_SCALE_FACTOR=0 labelme或者在图像尺寸特别大的情况下,先缩小图像再标注。Labelme 加载超大图片时会占用大量内存,图像模糊通常是缩放显示导致的,不是图像本身损坏,不用担心。
6.5 高频操作快捷键清单
快捷键是提高标注效率的关键。下面是我整理的一份常用快捷键表,不少功能藏在右键菜单里,直接记快捷键能省不少时间:
| 操作 | 快捷键 | 说明 |
|---|---|---|
| 上一张/下一张图片 | A / D | 翻图时不打断标注状态 |
| 保存 | Ctrl+S | 建议每张图都立即保存 |
| 撤销上一步 | Ctrl+Z | 可撤销误加的点 |
| 放大/缩小 | Ctrl+滚轮 | 精细标注时配合使用 |
| 删除选中标注 | Ctrl+Delete | 先选中对象再删除 |
| 完成当前多边形 | 双击鼠标左键 | 闭合多边形并弹出标签选择 |
| 编辑模式切换 | Ctrl+E | 在创建与编辑之间切换 |
这些快捷键不同版本可能略有差异,但大致相同。用熟练之后,眼睛只看图像,手不离鼠标和 Ctrl 键,效率会提升很多。
7. 写在最后:从标注新手到高效生产的进阶建议
现在你已经能把 Labelme 装起来,也知道怎么画多边形、怎么保存 JSON、怎么把数据转换成常见格式。最后分享几个我真正在项目里用下来觉得有用的经验。
第一,不要一上来就标几百张图。建议先用 20 张图跑通完整链路,包括标注、格式转换、模型训练和推理,确认整条流水线没有问题后,再放开手脚批量标注。否则等你辛辛苦苦标完 300 张,才发现自己标签类别定义和模型输出不一致,返工成本就非常高了。第二,类别定义要提前团队对齐,最好写一份标注规范文档,明确每个类别的边界、遮挡目标怎么标、模糊目标要不要标,这在多人协作时尤其重要。第三,善用脚本做自动化检查。我每次标注完一批数据,都会用几行 Python 检查 JSON 中points是否为空、label是否符合预期列表、是否有多余空白字符,这些细枝末节在训练时都会变成大坑。第四,如果后续数据量进一步增大,可以研究 Labelme 的二次开发接口,把简单的标注流程封装成自己的小工具,或者引入半自动标注模型做预付标,这已经是进阶方向了,但对生产效率的提升非常明显。
我自己的体会是,标注工具本身不复杂,真正拉开差距的是对标注规范和数据处理的理解。Labelme 给了我们一个足够开放的起点,后面的路完全看你怎么组织数据和优化流程。希望这篇文章能让你少踩几个 Windows 专属的坑,把更多时间和精力放到模型本身。如果你在实际操作中遇到其他问题,欢迎带着具体的报错信息再来交流,大概率是环境或路径上的小问题。