ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Labelme图像标注工具完全指南:安装、操作、格式转换与高效标注实践

Labelme图像标注工具完全指南:安装、操作、格式转换与高效标注实践 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 python3.8这里选Python 3.8而不是最新的版本是因为labelme虽然对Python版本不算挑剔但3.8到3.10之间的版本兼容性最稳。我分别在3.7、3.8、3.10上跑过labelme3.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再装labelmepip install PyQt5 pip install labelmeLinux用户如果是Ubuntu/Debian系的系统还有一条apt装法sudo apt install python3-labelme但这只适用于系统自带Python环境版本通常比较旧不利于后续配合SAM2等新功能一起用。推荐还是走conda pip的组合方案环境更干净、升级更方便。2. 打开labelme后的界面与多边形标注全流程2.1 界面里每个按钮是干什么的输入labelme启动后看到的是一个简洁到近乎朴素的界面。左侧竖排的工具栏、中间大面积画布区、右侧的标签文件列表整个界面没有任何多余的设计。对第一次接触标注工具的人来说这个界面其实让人有点懵我当初也是摸索了好一会儿才搞明白每个按钮的用途。左侧工具栏从上到下依次是Open打开单张图片适合快速标注一两张甚至就看一下效果。Open Dir打开一个文件夹批量加载里面的所有图片这是实际标注项目中最常用的入口。Next/Prev在批量打开的图片间前后切换标注完一张就切下一张。Save保存当前图片的标注结果快捷键是CtrlS。Create Polygons多边形标注也是labelme最重要的功能快捷键是CtrlP。Edit Polygons编辑已有标注可以拖动顶点、删除顶点、调整形状快捷键是CtrlJ。Delete删除当前选中的标注对象。画布区右击还能弹出更多操作选项比如复制多边形、编辑标签名、撤销上一步等。标注过程中最核心的产物是JSON文件。每标注完一张图片点击保存labelme会在图片同目录下生成一个同名的.json文件。这个文件里包含了图片尺寸、所有标注对象的轮廓坐标、标签名称等全部信息。后续无论是转成训练数据集还是人工检查标注质量都是以这个JSON文件为基准。2.2 多边形标注的完整操作流程多边形标注是目前最主流的标注方式语义分割、实例分割、目标检测都离不开它。为什么格式上要选多边形而不是直接画矩形或画点因为多边形的通用性最强——你可以在多边形基础上生成最小外接矩形做检测可以填充成mask做分割也可以提取点云做关键点任务。以不变应万变这是labelme默认标注方式就是多边形的原因。实际操作流程如下点击左侧的Open Dir选择存放图片的文件夹。点击Create Polygons或者按快捷键CtrlP然后在画布上对着目标物体的边缘每隔一定距离点一下鼠标左键沿着轮廓描点。描到闭合的时候把鼠标移到起点附近会出现一个高亮的圆形提示这时候点一下或者直接按回车键多边形就闭合了。闭合后会自动弹出输入框让你填写这个标注物体的标签名例如“car”或“person”填完确认。一张图上有多个目标就重复步骤2到4全部标注完按CtrlS保存。操作过程中有几个细节值得注意。首先描点不是越多越好。虽然点多了能更精确地贴合轮廓但也会带来两个问题一是标注效率断崖式下降二是后期如果做数据集增强或格式转换密集的点会显著增加计算量。合理的做法是在轮廓的拐角处和弧度变化大的地方多描点在直线段上隔一段距离描一个点就行。其次如果描错了怎么办按CtrlJ进入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, encodingutf-8) as f: data json.load(f) mask np.zeros((img_size[1], img_size[0]), dtypenp.uint8) for shape in data[shapes]: label shape[label] points np.array(shape[points], dtypenp.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_mappingclass_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、多边形坐标、最小外接矩形bboxcategories数组需要记录所有类别名和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, encodingutf-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, encodingutf-8) as f: json.dump(coco_data, f, ensure_asciiFalse, indent2) 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_okTrue) 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), quality95)图片数量特别多的情况建议按子文件夹分批次标注比如每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的保存逻辑是手动触发不像一些商业工具会自动保存。这就意味着如果不养成随手CtrlS的习惯遇到软件崩溃、断电或误关闭窗口就会丢失最近一段时间的标注成果。我个人的习惯是每标注完三到五个对象就按一次CtrlS不管这张图有没有全部标完。这样最多丢失几个对象的标注量不至于整张图重来。如果遇到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用得更顺手。
返回列表