资讯动态

labelme图像分割标注全指南:安装、JSON转换与避坑实践

发布时间:2026/10/15 4:16:59 来源:尧图企业网站定制
简介这份资源是面向计算机视觉、机器学习初学者及数据标注从业者的 Labelme 安装与使用教程文档帮助读者在 Windows 环境下完成从环境搭建到图像分割标注的完整流程。压缩包内共 1 个 docx 文件约 14KB以图文步骤形式组织内容便于按章节查阅与对照操作。教程覆盖安装 Anaconda、创建 labelme 虚拟环境、区分 Python2 与 Python3 的安装指令以及激活环境、启动工具、执行 labelme_json_to_dataset 转换 JSON 标注文件等关键环节并说明 label_viz.png 可视化结果的查看方式。目前已有 15225 人学习下载适合需要快速上手图像分割标注工具、搭建本地标注环境或排查安装报错的读者参考也可作为计算机视觉项目数据准备阶段的入门材料。1. 标注工具选型为什么 labelme 仍是分割任务的首选做图像分割的团队里数据标注往往是第一个卡住进度的环节。你可能已经试过用矩形框工具凑合结果发现边缘像素对不上模型训练时 loss 震荡得厉害也可能用过在线标注平台但数据要上传到外部服务器合规上过不去。labelme 这个工具之所以在分割任务里被反复提起核心原因就一个它把多边形、掩码、关键点这些标注形态做成了本地可跑、格式开放、能脚本批处理的形态。你装完就能离线用标完直接导出 JSON后续转 COCO 或 VOC 都有现成脚本。它适合谁适合手里有几百到几万张图、需要精细边缘、又不想被平台绑定的算法工程师和标注团队。这一章先把工具定位和适用边界说清楚后面再动手装。labelme 的本质是一个基于 Qt 的桌面标注程序作者是 MIT 的计算机视觉组但你在用的时候不需要关心这些背景只需要知道它输出的是标准 JSON每张图对应一个同名 .json 文件里面记录了多边形顶点坐标、标签名、图像尺寸。这个格式的好处是自描述你写个 Python 脚本就能批量转成训练框架要的格式。坏处也有它不帮你管理标注进度多人协作要靠自己搭目录规范。所以选型时要判断如果你的数据量在十万级以上或者需要多人实时协同labelme 单机模式会吃力得配合版本管理或自建标注流水线。但对大多数中小规模分割项目它是最短路径。安装方式上常见做法是 conda 建环境再 pip 装避免和系统 Python 冲突。Windows 用户直接下预编译包也能跑但后续要写转换脚本时还是得配 Python 环境不如一步到位。下面从环境准备开始把安装、启动、标注、导出、转换整条链路走一遍中间会穿插参数说明和踩坑记录。2. 从零装好 labelme环境隔离与三种安装路径2.1 用 conda 建独立环境再 pip 安装我一般不会在 base 环境里直接 pip install labelme因为它的依赖里有 PyQt5 和 numpy版本冲突起来很难查。先建一个 Python 3.9 的环境这个版本和 PyQt5 的兼容性最稳。# 创建名为 labelme_env 的独立环境指定 Python 3.9 conda create -n labelme_env python3.9 -y # 激活环境 conda activate labelme_env # 用 pip 安装 labelme不要用 conda install labelme pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple这里有个细节conda 的官方源里也有 labelme但更新往往滞后而且它会连带装一堆 conda 版的 Qt 库和 pip 版混用容易出图形界面崩溃。所以统一走 pip。安装完成后用labelme --version验证能打印出版本号就说明命令行入口正常。如果报command not found检查环境是否激活Windows 下还要确认 Scripts 目录在 PATH 里。2.2 Windows 免安装包与 macOS 的差异处理Windows 用户如果只是临时标几张图可以去项目 release 页下 exe双击就能跑。但我要提醒免安装包不带 Python 环境你没法用它跑批量转换脚本而且不同版本 exe 对高分辨率屏幕的缩放支持不一样4K 屏上可能界面模糊。长期做项目还是建议走 conda 路径。macOS 上装完后启动可能会报objc相关错误这是 PyQt5 在较新系统上的已知问题。解决办法是装pyqt5时指定版本或者用pip install labelme --no-deps再手动补依赖。更稳的做法是用 Python 3.9 加 PyQt5 5.15.4 的组合这个组合在 M1 和 Intel 芯片上都验证过。启动命令就是终端里敲labelme后面可以跟图片目录路径比如labelme /data/images这样打开就直接加载整个文件夹。2.3 启动参数与界面区域的功能划分labelme 启动时可以带几个常用参数我列在表里方便你按场景选。参数作用典型用法--output指定标注文件保存目录labelme --output /data/labels--nodata不保存图像数据到 JSON图片路径固定时减小 JSON 体积--autosave自动保存防止崩溃丢标注标注大图时建议开启--labels预定义标签列表文件多人协作统一标签名界面分四块左侧文件列表中间画布右侧标签列表顶部工具栏。画多边形用Create Polygon快捷键是 CtrlN。标完一个区域点右键选Edit Label改名字。这里有个血泪经验标签名一旦定好就不要中途改因为 JSON 里存的是字符串改完旧文件不会自动更新后续合并数据集时会出现同一类两个名字的情况。3. 标注操作与 JSON 输出从画点到导出掩码3.1 多边形标注的顶点策略与边缘贴合画多边形时顶点密度直接决定掩码质量。我见过新手沿着物体边缘疯狂点一张图点几百个点结果训练时 mask 边缘锯齿反而更严重。合理的做法是直线段两端各一个点曲线段按曲率每 10 到 20 像素一个点。对于 1024 分辨率的图一个中等复杂物体 30 到 50 个顶点足够。labelme 支持画完后拖动顶点微调按住 Ctrl 点边可以加点点顶点按 Delete 删点。还有一个隐藏功能Create Rectangle和Create Circle也能用但它们生成的 JSON 里 shape_type 不同转掩码时要单独处理。如果你做的是语义分割统一用 polygon 最省事。标注时把图像放大到 200% 以上再点边缘贴合度会明显提升这个习惯能帮你省掉后期大量修边时间。3.2 JSON 文件结构逐字段解读标完一张图旁边会生成同名 .json。用文本编辑器打开结构如下{ version: 5.1.1, flags: {}, shapes: [ { label: defect, points: [[100.5, 200.3], [150.2, 210.8], [160.0, 260.5]], group_id: null, shape_type: polygon, flags: {} } ], imagePath: 001.jpg, imageData: null, imageHeight: 1024, imageWidth: 1280 }shapes是核心数组每个元素是一个标注区域。points里是浮点坐标顺序就是画点顺序转掩码时用PIL.ImageDraw.polygon直接填充即可。imageData如果是 null说明启动时加了--nodata或者图片是以目录方式加载的。imageHeight和imageWidth用来校验坐标是否越界。注意version字段不同版本生成的 JSON 在flags和group_id上可能有差异写转换脚本时不要依赖这些可选字段。3.3 批量转换JSON 转 COCO 格式的脚本实现单张转换没意义实际项目都是几百张起。下面这个脚本把 labelme JSON 批量转成 COCO 的 instance segmentation 格式我用了 pycocotools 的接口直接生成可训练的标注文件。import json import os import numpy as np from PIL import Image from pycocotools import mask as mask_util def labelme_to_coco(json_dir, image_dir, output_json): coco { images: [], annotations: [], categories: [] } # 先扫描所有标签名建立类别索引 label_set set() json_files [f for f in os.listdir(json_dir) if f.endswith(.json)] for jf in json_files: with open(os.path.join(json_dir, jf), r, encodingutf-8) as f: data json.load(f) for shape in data[shapes]: label_set.add(shape[label]) categories [{id: i 1, name: name} for i, name in enumerate(sorted(label_set))] coco[categories] categories cat_id_map {c[name]: c[id] for c in categories} ann_id 1 for img_id, jf in enumerate(json_files, start1): with open(os.path.join(json_dir, jf), r, encodingutf-8) as f: data json.load(f) img_name data[imagePath] h, w data[imageHeight], data[imageWidth] coco[images].append({ id: img_id, file_name: img_name, height: h, width: w }) for shape in data[shapes]: points np.array(shape[points], dtypenp.float32) # 生成二值掩码 rle mask_util.frPyObjects([points.flatten().tolist()], h, w) rle mask_util.merge(rle) area float(mask_util.area(rle)) bbox mask_util.toBbox(rle).tolist() coco[annotations].append({ id: ann_id, image_id: img_id, category_id: cat_id_map[shape[label]], segmentation: rle, area: area, bbox: bbox, iscrowd: 0 }) ann_id 1 with open(output_json, w, encodingutf-8) as f: json.dump(coco, f, ensure_asciiFalse) print(f转换完成共 {len(coco[images])} 张图{len(coco[annotations])} 个标注) # 调用示例 labelme_to_coco(/data/labels, /data/images, /data/train_coco.json)逻辑说明先遍历所有 JSON 收集标签名排序后分配类别 id保证多次运行 id 稳定。然后逐图读取把多边形点转成 RLE 编码这是 COCO 分割标注的标准存储方式。frPyObjects接收的是扁平化的坐标列表merge把同一张图多个多边形合并。area和bbox是训练时计算 loss 和做 NMS 要用的字段不能省。参数上json_dir和image_dir要分开传因为 labelme 默认把 JSON 和图片放一起但实际项目里我习惯分目录存方便版本管理。4. 避坑与排查标注现场最常见的五类翻车4.1 启动报 Qt 平台插件错误现象命令行敲labelme后弹窗报could not load the Qt platform plugin xcb程序直接退出。原因PyQt5 的插件路径没被正确识别常见于 conda 环境和系统 Qt 混用。解决先pip uninstall pyqt5再pip install pyqt55.15.4然后设置环境变量export QT_DEBUG_PLUGINS1看具体缺哪个库。如果是 Linux 服务器无显示环境需要加export QT_QPA_PLATFORMoffscreen但这样只能跑脚本不能交互标注。4.2 标注文件与图片不同名导致加载失败现象打开 labelme 指定目录图片显示但标注不出现。原因labelme 靠文件名匹配001.jpg必须对应001.json如果 JSON 是001_标注.json就认不到。解决批量重命名用脚本把 JSON 文件名改成和图片一致。另外注意扩展名大小写001.JPG和001.jpg在 Linux 下是两个文件Windows 下不区分但传到服务器就出问题。4.3 大图标注卡顿与内存溢出现象标注 4000x3000 以上的图时画布拖动延迟明显点几十个点后程序无响应。原因labelme 默认把整图加载进内存并实时渲染图越大 Qt 绘制压力越大。解决标注前把图缩放到 2000 像素以内或者用--nodata启动减少 JSON 体积。如果必须标原图开启--autosave每标几个点就保存崩了也不丢。我一般会先用脚本把超大图切块标完再合并这样单块内存占用可控。4.4 标签名带空格或特殊字符现象转换 COCO 时类别名出现defect带尾空格或者a/b这种斜杠导致后续训练读类别报错。原因标注时手动输入标签容易多敲空格或用了路径符号。解决用--labels参数加载预定义标签文件文件里每行一个标签名标注时只能从列表选从源头杜绝手误。已经标完的用脚本批量 strip 和替换特殊字符。4.5 多人标注后合并 JSON 冲突现象两个人标同一批图合并时发现同一张图有两个 JSON或者标签名一个用中文一个用英文。原因没有统一标签规范和文件命名规范。解决项目开始前定好标签文件所有人用同一个--labels文件按原图名.json存不要加人名后缀合并时用脚本按 imagePath 去重冲突的以标注区域多的为准。更稳的做法是每人一个目录最后统一转换再合并 COCO避免直接改 JSON。5. 进阶技巧用脚本做标注质量抽检与半自动预标注5.1 标注质量抽检面积与顶点数异常检测标完几千张图人工逐张检查不现实。我一般写个脚本跑一遍统计把异常图筛出来重点看。异常判断逻辑单个多边形面积占比超过图像 80% 的可能是误框了整个背景顶点数少于 5 的可能是点太快漏了同一标签在相邻图里面积突变超过 3 倍的可能是标错类别。import json import os import numpy as np from PIL import Image, ImageDraw def check_annotation_quality(json_dir, image_dir, area_ratio_th0.8, min_points5): suspicious [] for jf in os.listdir(json_dir): if not jf.endswith(.json): continue with open(os.path.join(json_dir, jf), r, encodingutf-8) as f: data json.load(f) h, w data[imageHeight], data[imageWidth] img_area h * w for shape in data[shapes]: pts shape[points] if len(pts) min_points: suspicious.append((jf, shape[label], 顶点过少, len(pts))) continue # 用 shoelace 公式算多边形面积 x [p[0] for p in pts] y [p[1] for p in pts] area 0.5 * abs(sum(x[i] * y[i1] - x[i1] * y[i] for i in range(-1, len(pts)-1))) if area / img_area area_ratio_th: suspicious.append((jf, shape[label], 面积占比过大, round(area/img_area, 2))) for s in suspicious: print(s) return suspicious check_annotation_quality(/data/labels, /data/images)这个脚本跑完会打印可疑列表你按文件名去 labelme 里复查就行。参数area_ratio_th默认 0.8对缺陷检测场景可以调到 0.5因为缺陷通常不会占大半张图。min_points设 5 是底线实际曲线物体建议设 15。5.2 半自动预标注模型输出转 labelme JSON当你有了一批训练好的模型可以先跑推理生成粗掩码再转成 labelme JSON 让人工修边效率能提升三到五倍。转换的核心是把二值掩码轮廓提取出来再写成 labelme 的 shapes 格式。import json import numpy as np import cv2 def mask_to_labelme_json(mask_path, image_path, label_name, output_json): mask cv2.imread(mask_path, cv2.IMREAD_GRAYSCALE) h, w mask.shape contours, _ cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) shapes [] for cnt in contours: if cv2.contourArea(cnt) 50: # 过滤小噪点 continue # 轮廓点简化减少顶点数 epsilon 0.002 * cv2.arcLength(cnt, True) approx cv2.approxPolyDP(cnt, epsilon, True) points approx.reshape(-1, 2).tolist() shapes.append({ label: label_name, points: points, group_id: None, shape_type: polygon, flags: {} }) data { version: 5.1.1, flags: {}, shapes: shapes, imagePath: image_path, imageData: None, imageHeight: h, imageWidth: w } with open(output_json, w, encodingutf-8) as f: json.dump(data, f, ensure_asciiFalse) mask_to_labelme_json(/pred/001_mask.png, 001.jpg, defect, /labels/001.json)这里approxPolyDP的 epsilon 控制简化程度0.002 倍周长在多数场景下能保留形状又不会点太多。过滤面积小于 50 像素的轮廓避免模型噪点变成无效标注。生成的 JSON 直接放进 labelme 目录就能打开修人工只需要拖顶点微调不用从零画。5.3 标注进度管理与版本回滚习惯多人协作时我习惯在标注目录里放一个progress.csv每标完一张就追加一行文件名、标注人、时间、状态。用脚本统计完成率比问进度靠谱。另外 labelme 没有内置版本控制但 JSON 是纯文本可以直接用 git 管理。每次批量标注前 commit 一次改坏了能回滚。这个习惯救过我一次某次批量替换标签名脚本写错把defect全改成了defect1靠 git 五分钟恢复。标注数据是模型的上限花在管理上的时间不会白费。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑