☰
Labelme图像标注工具完全指南:安装、操作、格式转换与高效标注实践
2026/10/1 9:15:32 网站建设 项目流程

1. 在Windows和Linux上安装labelme:两种环境下的完整流程

1.1 用Anaconda隔离Python环境,避免踩版本坑

很多第一次接触labelme的朋友,第一反应是直接打开终端输入pip install labelme。这个思路没错,但我强烈建议先装Anaconda,为labelme单独创建一个虚拟环境。原因很简单:labelme依赖PyQt和多个图像处理库,如果直接安装到系统Python里,极有可能和已有的包产生版本冲突。我见过不少人在系统环境里装完labelme,启动的时候直接报错,或者把别的项目的依赖搞崩,最后只能整机重配环境,十分痛苦。

虚拟环境的概念可以用一个生活场景来理解:你在同一套房子里,想让一个喜欢熬夜的室友和一个喜欢早睡的室友互不打扰,最好的办法是给他们各自独立的房间。conda虚拟环境就是给Python程序各自开的“房间”,每个房间里的依赖互相隔离,labelme的安装和使用不会影响你其他项目的运行环境。

创建环境的命令很简单:

conda create -n labelme python=3.8

这里选Python 3.8而不是最新的版本,是因为labelme虽然对Python版本不算挑剔,但3.8到3.10之间的版本兼容性最稳。我分别在3.7、3.8、3.10上跑过labelme,3.8的表现最省心,几乎不会遇到缺依赖或编译报错的情况。

创建好环境以后,激活它:

conda activate labelme

激活成功的话,终端命令行前面会多出一个(labelme)前缀,这就代表你现在已经在独立的labelme环境里了。后续所有操作都在这个环境下执行。

1.2 Windows安装:从新建环境到敲出labelme命令

在Windows上装labelme,很多教程只告诉你装个Anaconda然后pip,但实际坑比想象中多。这里我把完整流程走一遍,你照着操作基本不会出问题。

激活环境后,直接安装:

pip install labelme

这一步正常情况下会自动拉取依赖,包括PyQt5、opencv-python、numpy等。如果网络状况不太理想,可以用国内镜像源替代,速度快很多:

pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple

安装完成后,验证是否成功:

labelme --version

能输出版本号(比如3.16.7),就说明安装成功。这时候在终端里直接输入labelme,就能打开图形界面。

有一个Windows特有的坑要提醒:如果命令提示符用的是系统自带的PowerShell,可能会出现环境激活不生效的情况。这时候建议切换到Anaconda Prompt来操作,或者先执行conda init powershell初始化一下,再重新打开PowerShell。我在Windows上踩过这个坑,当时还以为自己环境装坏了,后来换到Anaconda Prompt,一切正常。

显卡不太好的电脑也不用担心,labelme本身对硬件要求很低,它只是用来标注的工具,不涉及训练,只要别同时打开几百张超大分辨率的图片,一般电脑都能流畅运行。

1.3 Linux/macOS安装:同一条命令,留意权限问题

Linux和macOS的安装流程跟Windows基本一致,也是创建虚拟环境后pip安装。但有一个额外注意点:如果用系统Python直接pip安装,经常会遇到“externally-managed-environment”的报错,这是新版Python对系统环境的保护机制。解决办法很简单,就是用conda建虚拟环境,别往系统环境里硬塞。

macOS用户如果是Apple Silicon芯片(M1/M2/M3),安装PyQt相关依赖时偶尔会有点小波折。如果pip install labelme后启动报错或窗口显示异常,可以试试先单独安装PyQt5再装labelme:

pip install PyQt5 pip install labelme

Linux用户如果是Ubuntu/Debian系的系统,还有一条apt装法:

sudo apt install python3-labelme

但这只适用于系统自带Python环境,版本通常比较旧,不利于后续配合SAM2等新功能一起用。推荐还是走conda + pip的组合方案,环境更干净、升级更方便。

2. 打开labelme后的界面与多边形标注全流程

2.1 界面里每个按钮是干什么的

输入labelme启动后,看到的是一个简洁到近乎朴素的界面。左侧竖排的工具栏、中间大面积画布区、右侧的标签文件列表,整个界面没有任何多余的设计。对第一次接触标注工具的人来说,这个界面其实让人有点懵,我当初也是摸索了好一会儿才搞明白每个按钮的用途。

左侧工具栏从上到下依次是:

  • Open:打开单张图片,适合快速标注一两张甚至就看一下效果。
  • Open Dir:打开一个文件夹,批量加载里面的所有图片,这是实际标注项目中最常用的入口。
  • Next/Prev:在批量打开的图片间前后切换,标注完一张就切下一张。
  • Save:保存当前图片的标注结果,快捷键是Ctrl+S。
  • Create Polygons:多边形标注,也是labelme最重要的功能,快捷键是Ctrl+P。
  • Edit Polygons:编辑已有标注,可以拖动顶点、删除顶点、调整形状,快捷键是Ctrl+J。
  • Delete:删除当前选中的标注对象。

画布区右击还能弹出更多操作选项,比如复制多边形、编辑标签名、撤销上一步等。

标注过程中最核心的产物是JSON文件。每标注完一张图片,点击保存,labelme会在图片同目录下生成一个同名的.json文件。这个文件里包含了图片尺寸、所有标注对象的轮廓坐标、标签名称等全部信息。后续无论是转成训练数据集,还是人工检查标注质量,都是以这个JSON文件为基准。

2.2 多边形标注的完整操作流程

多边形标注是目前最主流的标注方式,语义分割、实例分割、目标检测都离不开它。为什么格式上要选多边形而不是直接画矩形或画点?因为多边形的通用性最强——你可以在多边形基础上生成最小外接矩形做检测,可以填充成mask做分割,也可以提取点云做关键点任务。以不变应万变,这是labelme默认标注方式就是多边形的原因。

实际操作流程如下:

  1. 点击左侧的Open Dir,选择存放图片的文件夹。
  2. 点击Create Polygons,或者按快捷键Ctrl+P,然后在画布上对着目标物体的边缘,每隔一定距离点一下鼠标左键,沿着轮廓描点。
  3. 描到闭合的时候,把鼠标移到起点附近,会出现一个高亮的圆形提示,这时候点一下,或者直接按回车键,多边形就闭合了。
  4. 闭合后会自动弹出输入框,让你填写这个标注物体的标签名,例如“car”或“person”,填完确认。
  5. 一张图上有多个目标就重复步骤2到4,全部标注完按Ctrl+S保存。

操作过程中有几个细节值得注意。首先,描点不是越多越好。虽然点多了能更精确地贴合轮廓,但也会带来两个问题:一是标注效率断崖式下降,二是后期如果做数据集增强或格式转换,密集的点会显著增加计算量。合理的做法是,在轮廓的拐角处和弧度变化大的地方多描点,在直线段上隔一段距离描一个点就行。

其次,如果描错了怎么办?按Ctrl+J进入Edit Polygons模式,可以拖动已有顶点微调位置。想删除某个点,按住Shift键再点击那个点即可。如果整个多边形都不想要了,先选中它,再按Delete键。这些快捷键虽然要花一点时间记忆,但用顺手之后,标注效率能提升一倍以上,强烈建议不要全程用鼠标点菜单。

还有一个很多人不知道的小技巧:描点过程中如果中途想放弃当前多边形,直接按Esc键就能退出,不会保留当前未闭合的部分。

2.3 矩形、圆形、线段和点标注:按任务需求选择

多边形虽然通用,但有些任务类型用其他形状效率更高。labelme把这些标注工具都内置了,在右键菜单或者编辑模式下可以切换。

矩形标注适合目标检测场景,尤其是物体轮廓本身接近矩形的,比如车牌、书本、电箱、建筑窗户等。直接用鼠标拖一个框就行,比手动描四个点多边形快得多。如果你的项目最终要转成VOC或COCO格式做目标检测,矩形标注是最省事的选择。

圆形标注适合标注圆形物体,比如细胞、硬币、轮胎等,鼠标按下后拉出半径即可。线段标注一般用于车道线、血管等线状目标的标注,点两个端点就完成一条线。点标注则用于关键点检测场景,比如人体姿态估计、关键部位定位等。

我在实际项目里的体会是:不要拘泥于一种标注方式,而是要看你最终需要什么类型的监督信号。如果模型输出是分割mask,就用多边形精细标注;如果只是检测框,矩形就足够了;如果做关键点任务,点标注直接对应真值。选对了标注方式,能省掉后期大量格式转换和二次标注的时间。

3. 标注结果的导出与格式转换

3.1 读懂JSON文件的结构,后续一切操作的基础

每张标注完成的图片,保存后都会生成对应的JSON文件。这些文件看起来是纯文本内容,但实际上你不需要记住每个字段,只需要理解核心的几个。

JSON里最重要的字段是shapes,这是一个列表,里面每一项代表一个标注对象。每个对象有几个关键信息:label字段是该对象的标签名,如“cat”;points字段是多边形顶点坐标的列表,每个顶点是一个[x, y]数组;shape_type字段表示标注形状类型,可能是“polygon”、“rectangle”、“circle”等。

另外还有imagePath字段,记录的是对应的图片文件名;imageWidth和imageHeight是图片的宽高,这对后期坐标换算很重要。例如,如果你要把标注结果用于一个要求输入尺寸固定的模型,就得根据原始宽高做归一化或缩放计算。

我这里提一个新手常犯的错误:直接手动改JSON文件里的坐标或标签名。JSON文件对格式要求非常严格,少一个逗号或多一个花括号,整个文件就解析失败。所以尽量在labelme界面里通过编辑功能修改,除非你是在写脚本批量处理。

3.2 用自带的转换命令,快速生成单张mask图

labelme框架自带一个命令行工具,可以方便地把JSON转成单通道的掩码图。操作如下:

labelme_json_to_dataset 图片名.json

执行后会在同目录下生成一个以“图片名_json”命名的文件夹,里面包含:

  • img.png:原图,相当于把原始图片复制了一份。
  • label.png:标签掩码图,前景物体被标记为白色(或具体类别对应的像素值),背景为黑色。
  • label_viz.png:可视化图,把标注轮廓以彩色形式叠加在原图上,方便人工检查标注效果。
  • label.txt:记录每个像素值对应标签名称的文本文件。

这个方法适合快速检查和单张转换。但如果你的项目有几百上千张图,一条一条执行命令就太痛苦了。这种场景下应该写个批处理脚本,不依赖labelme自带的命令,而是直接读取JSON文件,用OpenCV和numpy解析出轮廓坐标,再填充成掩码。

这里分享一个我自己常用的批量转换脚本,逻辑很清晰,直接修改路径就能用:

import json import numpy as np import cv2 import os def json_to_mask(json_path, img_size, class_mapping): with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) mask = np.zeros((img_size[1], img_size[0]), dtype=np.uint8) for shape in data["shapes"]: label = shape["label"] points = np.array(shape["points"], dtype=np.int32) class_id = class_mapping[label] cv2.fillPoly(mask, [points], class_id) return mask # 使用示例 class_mapping = {"background": 0, "car": 1, "person": 2} for json_file in os.listdir("./annotations"): if not json_file.endswith(".json"): continue mask = json_to_mask( os.path.join("./annotations", json_file), img_size=(1920, 1080), class_mapping=class_mapping ) out_path = os.path.join("./masks", json_file.replace(".json", ".png")) cv2.imwrite(out_path, mask)

这段代码的核心逻辑是:加载JSON,逐条取出每个标注对象的轮廓点和标签,用cv2.fillPoly把轮廓内部填充成对应的类别ID,最后得到一张与图片尺寸相同的掩码图。相比官方命令,这个脚本的优势在于:可以在不同项目中灵活替换类别映射表,支持多类别标注,而且直接输出训练所需的单通道图。

3.3 转换COCO格式做目标检测,收藏这份经典脚本

如果你做的是目标检测,需要把labelme标注结果转成COCO格式。COCO格式本质上是一个大JSON文件,里面包含images、annotations、categories三个核心数组。转换逻辑不复杂,但细节比较多,很多人到这一步就卡住了。

images数组需要记录每张图片的id、文件名、宽高;annotations数组需要记录每个标注对象的id、所属图片id、类别id、多边形坐标、最小外接矩形bbox;categories数组需要记录所有类别名和id。

下面是我整理的一份可直接使用的转换脚本,你可以把它保存成labelme2coco.py,配合命令行使用:

import json import os import numpy as np from PIL import Image def convert_labelme_to_coco(labelme_dir, output_path, categories): images = [] annotations = [] ann_id = 1 img_id = 1 category_id_map = {cat["name"]: cat["id"] for cat in categories} for filename in os.listdir(labelme_dir): if not filename.endswith(".json"): continue json_path = os.path.join(labelme_dir, filename) with open(json_path, "r", encoding="utf-8") as f: data = json.load(f) image_path = os.path.join(labelme_dir, data["imagePath"]) image = Image.open(image_path) width, height = image.size images.append({ "id": img_id, "file_name": data["imagePath"], "width": width, "height": height }) for shape in data["shapes"]: points = shape["points"] polygon = [coord for point in points for coord in point] x_coords = [p[0] for p in points] y_coords = [p[1] for p in points] bbox = [min(x_coords), min(y_coords), max(x_coords) - min(x_coords), max(y_coords) - min(y_coords)] annotations.append({ "id": ann_id, "image_id": img_id, "category_id": category_id_map[shape["label"]], "segmentation": [polygon], "area": bbox[2] * bbox[3], "bbox": bbox, "iscrowd": 0 }) ann_id += 1 img_id += 1 coco_data = { "images": images, "annotations": annotations, "categories": categories } with open(output_path, "w", encoding="utf-8") as f: json.dump(coco_data, f, ensure_ascii=False, indent=2) print(f"转换完成,共 {len(images)} 张图片,{len(annotations)} 个标注对象")

用法很简单,把labelme_dir改成存放JSON的目录,把categories改成自己的类别列表,比如:

categories = [ {"id": 1, "name": "car"}, {"id": 2, "name": "person"}, {"id": 3, "name": "bicycle"} ]

然后运行脚本,就会在指定路径生成一个coco格式的JSON文件。这个文件可以直接喂给mmdetection、detectron2或YOLO的COCO数据处理流程。

4. 批量标注中能提升效率的几个关键配置

4.1 提前规划标签命名规范,比后期返工省时百倍

标注进度过半后才意识到标签命名不一致,是很多团队踩过的大坑。比如同一辆车的标注,组员A写“car”,组员B写“CAR”,组员C写“vehicle”,最后做类别合并时要写额外脚本去映射,稍微不慎,整个数据集的类别数量都是错的。

合理的做法是:标注开始前,先用一个类别清单把所有标签名定死,甚至可以考虑直接修改labelme源码中的预定义类别列表,让组员只能从下拉列表中选择标签,从源头杜绝命名不一致。

具体操作可以参考labelme项目里一个分支提供的方案:在应用启动时加载指定的标签文件,而不是使用默认的未分类列表。如果你不愿改动源码,也可以用另一种方式:手动在项目目录组织一个labels.txt,标注时对照清单填写,并要求所有组员严格遵守。

实际操作中我还发现一个细节:让标注人员对“难样本”提前达成共识。比如一辆车被树遮挡了一半,边界应该画到遮挡处还是在遮挡处补全?这种模糊边界如果不提前定义规则,每个人都有自己的判断,最终标注质量差异非常大。建议在标注开始前挑出几张典型图片,规定统一的标注规范,并检视前几十张的标注结果,及时纠偏。

4.2 在labelme中部署SAM2,半自动标注直接把效率拉满

如果只做纯手动标注,一张复杂图像标10个物体可能要花5到10分钟,一天下来效率非常有限。后来我尝试把Meta开源的SAM2模型接入labelme,利用自动分割能力做半自动标注,效率提升非常明显。

所谓“在labelme中部署SAM2”,本质上就是利用SAM2的自动分割能力——你只需要在目标物体上点一下,SAM2就能自动生成一个高质量的分割掩码。你用这个掩码替换手动描多边形的过程,再保存为labelme的标注格式。对轮廓复杂、目标边缘不规则的物体来说,比手工描点省太多事了。

具体部署步骤是这样的:

首先确保电脑有NVIDIA显卡,显存最好在8GB以上,否则SAM2的推理速度会很慢,或者直接OOM。然后克隆SAM2仓库并安装:

git clone https://github.com/facebookresearch/sam2.git cd sam2 pip install -e .

接着下载模型权重,推荐使用sam2.1_hiera_large.pt或sam2.1_hiera_base_plus.pt,前者精度高但更吃显存,后者速度快很多,实测在RTX 3060上也能跑起来,推理时间大概在1到3秒之间。

配置好SAM2模型后,用labelme的API加载模型,在标注界面点选目标时调用SAM2的推理接口生成mask,再把mask转换成多边形点坐标写回labelme的JSON结构。这种半自动标注方式特别适合语义分割数据集的构建,尤其是那些物体轮廓复杂、重复性高的场景。

我自己的实际体验是:对一张含5到10个复杂目标的街景图,纯手动标注需要8分钟左右,接入SAM2后两分钟左右就能完成。不过也有一个要注意的地方:SAM2在物体边缘跟背景颜色相近、或者有光照遮挡的情况下,分割结果不一定完全准确。这时候不要直接保存,要进入编辑模式,手动调整多边形顶点,把错误边缘改正后再保存。半自动标注不是全自动标注,最后的质量还是需要人工把关。

4.3 处理大图和超大目录:预压缩与分批标注

很多图像标注项目拿到的原图都是几MB甚至几十MB的高分辨率图像。直接加载到labelme里,界面会卡顿,缩放和拖动都会掉帧,标注体验非常糟糕。这个问题在Windows上尤其明显,因为Windows的图形渲染管线对超大窗口支持相对弱一些。

一个有效的做法是,在标注前先用脚本把所有图片压缩到合适的分辨率(比如1920x1080或2048x1536)。压缩后的图片用于标注,标注完得到的坐标也基于这个分辨率。如果最终训练时要使用原始分辨率,只需在预处理阶段做一次坐标等比放大。

批量压缩的脚本很简单:

from PIL import Image import os input_dir = "./original" output_dir = "./compressed" target_size = (1920, 1080) os.makedirs(output_dir, exist_ok=True) for filename in os.listdir(input_dir): if filename.lower().endswith((".jpg", ".jpeg", ".png")): img = Image.open(os.path.join(input_dir, filename)) img.thumbnail(target_size, Image.LANCZOS) img.save(os.path.join(output_dir, filename), quality=95)

图片数量特别多的情况,建议按子文件夹分批次标注,比如每200到300张一个批次,一方面方便检查质量,另一方面避免打开文件夹时labelme一次性加载太多图片导致内存飙升甚至崩溃。

5. 常见问题与排错实录

5.1 安装报错与界面启动失败的处理方案

labelme虽然在安装上已经很省心,但不同电脑环境总会有各种意外。我把我在不同设备上遇到过的典型问题和解决方案整理成一个速查表,方便你直接对照排查。

现象可能原因解决方案
pip install labelme进度条卡死网络问题,默认源连接不稳定更换清华镜像源:pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple
安装报错:ERROR: Could not install packages...权限不足或环境冲突确认已激活conda环境;Windows下用Anaconda Prompt执行
启动后弹窗立即闪退PyQt5依赖损坏或版本不兼容pip uninstall PyQt5 PyQt5-Qt5 PyQt5-sip后重新安装labelme
界面打开但图片不显示图片路径含中文或特殊字符把图片目录和文件名统一改成英文
labelme命令无法识别环境变量或激活状态异常重新激活环境,输入python -m labelme试一下
批量打开文件夹时内存溢出图片数量太多或单张过大按子目录分批标注,使用压缩后的图片

遇到过最奇怪的一个案例是,一台Windows电脑上labelme明明安装成功,但启动后界面一直是半透明的,鼠标点击没有反应。排查了一圈,最后发现问题出在显卡驱动上——机器是老显卡,自带的OpenGL驱动太旧,PyQt5的窗口渲染出了问题。更新驱动后一切正常。如果你的电脑也出现类似问题,优先检查显卡驱动版本。

5.2 标注过程中的数据丢失与恢复手段

标注工具最大的痛点之一,是害怕辛辛苦苦标注的成果突然丢失。labelme的保存逻辑是手动触发,不像一些商业工具会自动保存。这就意味着:如果不养成随手Ctrl+S的习惯,遇到软件崩溃、断电或误关闭窗口,就会丢失最近一段时间的标注成果。

我个人的习惯是:每标注完三到五个对象就按一次Ctrl+S,不管这张图有没有全部标完。这样最多丢失几个对象的标注量,不至于整张图重来。

如果遇到labelme打开JSON文件时提示解析错误,先别急着重新标注。用文本编辑器打开那个JSON文件,检查是不是缺了结尾的}或者某个字符串引号没闭合。如果只是小范围格式问题,手工修复即可。另外,Windows系统如果开启了文件历史记录或还原点,也可以尝试从以前的版本中恢复文件。

针对批量标注项目,我强烈建议每天工作结束后把所有JSON文件打包备份一次,可以用压缩软件或命令行完成。一旦出现硬盘故障或误删,最多损失一天的工作量,不至于整个项目都要重来。

5.3 坐标精度与后续训练的衔接技巧

用labelme标注出的坐标是绝对的像素坐标,直接拿去做模型训练,一般没问题。但如果训练时的输入尺寸需要固定(比如统一缩放到512x512),那就要在数据预处理阶段把标注坐标也按照同样的缩放比例转换。

这里有一个典型的误区:只把图片缩放,却没有同步缩放标注坐标,导致训练时所有bbox或mask位置整体偏移,模型完全学不到正确信息。正确做法是记录原始尺寸,然后统一处理图片和标注:

scale_x = target_width / original_width scale_y = target_height / original_height new_points = [[p[0] * scale_x, p[1] * scale_y] for p in points]

如果图片被旋转或翻转做了数据增强,标注坐标也要做相同的几何变换。我当时做目标检测项目时,因为忽略了这一步,增强后的数据里有一大半框都不准,排查了很久才发现是坐标没有同步变换,白白浪费了两天时间。提前把这条逻辑写进增强代码里,能避免很多后续麻烦。

对于需要极坐标精度的项目(比如医学图像分割),可以开启labelme的“顶点编辑吸附”功能,让描点时自动吸附到图像边缘的像素级轮廓上,这样标注结果更精细,能直接提升分割模型的上限表现。

最后再分享几个实践经验

labelme用久了,我最大的感受是:工具本身只是一部分,真正影响项目进度的往往是规范管理和细节把控。标注之前把环境、标签规范、图片尺寸、坐标转换逻辑都提前规划好,后续就会省心得多。如果你刚开始接触标注,可以先拿一二十张图练手,把软件操作和格式转换都跑通,再开始大规模标注,避免批量返工。

如果你后续想扩展功能,还可以研究一下labelme的源码,把自定义的预训练模型接进去做辅助标注,或者把标注结果接上可视化平台做团队审查。标注工具本身虽然简单,但围绕它构建的工程流程,才是质量和效率的真正保障。希望这篇文章能帮你把labelme用得更顺手。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询