简介LabelImg-master.zip 是一款面向计算机视觉从业者与深度学习入门者的开源图像标注工具源码包主要用于为目标检测、语义分割等卷积神经网络任务快速构建高质量训练数据集。它提供直观的图形界面支持矩形框、多边形等多种标注形式标注结果可保存为 XML 或 JSON 格式并兼容 Windows、Mac OS 与 Linux 平台非编程背景人员也能快速上手。压缩包共 108 个文件约 6.29MB以 27 个 py 源码文件、39 个 png 界面素材、6 个 svg 图标及若干 sh 脚本、rst 文档、properties 配置为主另附安装方法与常见错误解决说明便于读者直接运行、二次开发或排查环境依赖问题。目前已有 425 人学习下载适合需要搭建标注流程、准备训练数据或研究标注工具实现细节的读者参考使用。1. 拆开 labelImg-master.zip一个标注工具凭什么成了算法团队的标配如果你正在做目标检测不管是 YOLO 系列还是 SSD、Faster R-CNN第一道绕不过去的坎就是标注数据。我见过太多团队在模型结构上反复调参结果 mAP 上不去回头一查发现标注框歪了三五个像素。labelImg 这个工具就是专门解决这个问题的——它是一个用 Python Qt 写的轻量级图像标注工具核心功能就一件事在图片上画矩形框、打类别标签然后导出成模型训练能直接吃的格式。这个 zip 包拿到手解压出来就是完整源码不需要编译装好依赖就能跑。它适合谁刚入门神经网络、准备自己搞数据集的学生需要快速给几百张图打框验证想法的算法工程师以及那些不想为了标注这件事去部署一套重型标注平台的小团队。它不花哨但足够稳这也是为什么这么多年过去它依然是很多人标注流程里的第一站。2. 环境搭建与首次启动从解压到画出第一个框2.1 依赖选型为什么是 PyQt5 而不是 PyQt6labelImg 的界面层用的是 PyQt但版本选择上有讲究。源码里默认走的是 PyQt5 的 API如果你直接 pip install PyQt6启动时会报一堆枚举类型不匹配的错误因为 Qt6 把很多常量挪了位置。我一般会先确认 Python 版本3.8 到 3.10 之间最稳3.11 以上偶尔会遇到 lxml 编译问题。安装依赖的命令如下# 建议在虚拟环境里操作避免污染全局包 python -m venv labelenv source labelenv/bin/activate # Windows 用 labelenv\Scripts\activate # 核心依赖PyQt5 负责界面lxml 负责解析 XML 标注文件 pip install PyQt55.15.9 lxml这里锁 PyQt5 的版本是有血泪经验的。5.15 系列是最后一个支持 Python 3.10 的稳定分支再往上走某些 Linux 发行版自带的 Qt 库会和 pip 装的冲突导致启动时提示 “could not load the Qt platform plugin xcb”。遇到这个报错先检查系统有没有装 libxcb-xinerama0没有就补上。2.2 启动方式与工作目录约定解压后进入目录你会看到 labelImg.py 这个入口文件。启动命令很简单# 在源码根目录执行 python labelImg.py # 如果想直接打开某个图片文件夹可以带参数 python labelImg.py /path/to/your/images启动后界面分三块左侧文件列表、中间画布、右侧标签列表。第一次用的时候很多人会直接点 “Open Dir” 选图片文件夹然后就开始画框。但这里有个隐藏顺序问题如果你先打开图片目录再点 “Change Save Dir” 指定标注保存位置已经画好的框会默认存到图片同级目录下。我习惯的做法是先建一个空的 annotations 文件夹启动后第一件事就是 Change Save Dir 指过去再 Open Dir 加载图片。这样标注文件和原图分离后面写数据加载脚本时路径清晰不会把原图目录搞得乱七八糟。2.3 标注格式切换Pascal VOC 与 YOLO 的取舍labelImg 支持两种主流导出格式切换按钮在左侧工具栏。Pascal VOC 生成的是 XML 文件每个框记录 xmin、ymin、xmax、ymax 四个绝对坐标YOLO 格式生成的是 txt 文件每行是 “类别索引 中心x 中心y 宽 高”全部归一化到 0 到 1 之间。选哪个取决于你的训练代码。如果你用的是 Ultralytics 的 YOLOv5/v8 仓库它默认读 YOLO 格式的 txt那就在标注前把格式切到 YOLO。但要注意YOLO 格式的类别是数字索引labelImg 里你需要先在 “predefined_classes.txt” 里写好类别名它按行号映射成 0、1、2。这个文件放在源码 data 目录下改完重启生效。如果类别写错了顺序后面训练时模型学到的类别就全乱了这种坑我踩过不止一次。3. 标注流程拆解从快捷键到批量校验的完整链路3.1 核心快捷键与画框逻辑labelImg 的效率高低八成取决于你熟不熟快捷键。画框用 W画完自动弹出类别选择下一张用 D上一张用 A。如果框画歪了CtrlZ 撤销上一步但注意它只能撤销当前图片的操作切到下一张再回来之前的撤销记录就没了。画框的时候有个细节鼠标拖拽的起点和终点决定了框的方向但 labelImg 会自动把坐标整理成左上角到右下角的标准形式。不过如果你拖拽时手抖框的宽高可能只有几个像素这种框在训练时会被当成噪声。我一般会目测一下宽高小于 10 像素的框直接删掉重画别指望模型能学到东西。3.2 类别管理与预定义标签文件前面提到的 predefined_classes.txt格式就是一行一个类别名不要有空行不要有空格。比如person car traffic_light保存后重启 labelImg右侧标签列表就会按这个顺序显示。标注时按对应的数字键 1、2、3 可以快速选类别比鼠标点快得多。如果中途需要加新类别改完文件重启就行已经标好的框不受影响因为 XML 或 txt 里存的是类别名或索引不是内存里的临时状态。这里有个容易翻车的地方如果你用 YOLO 格式标注中途改了 predefined_classes.txt 的顺序之前标好的 txt 文件里的索引就对不上了。比如原来 0 是 person你改成 0 是 car那旧文件全错。所以类别列表一旦定下来尽量别动顺序要加就往后追加。3.3 标注文件的组织与校验脚本标完一批图之后别急着扔给训练脚本。我习惯先跑一个校验脚本检查有没有空文件、坐标越界、类别名拼写错误。下面这个 Python 脚本可以快速扫一遍 Pascal VOC 格式的 XMLimport os import xml.etree.ElementTree as ET def validate_annotations(anno_dir, img_dir): issues [] for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue xml_path os.path.join(anno_dir, xml_file) tree ET.parse(xml_path) root tree.getroot() # 检查对应的图片是否存在 img_name root.find(filename).text if not os.path.exists(os.path.join(img_dir, img_name)): issues.append(f{xml_file}: 图片 {img_name} 不存在) # 检查每个框的坐标 for obj in root.findall(object): bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) if xmin xmax or ymin ymax: issues.append(f{xml_file}: 坐标顺序错误 {xmin},{ymin},{xmax},{ymax}) if xmin 0 or ymin 0: issues.append(f{xml_file}: 坐标越界) return issues # 用法示例 problems validate_annotations(./annotations, ./images) for p in problems: print(p)这个脚本的逻辑很直白遍历标注目录解析每个 XML先确认图片文件还在再检查框的坐标是否合法。参数说明一下anno_dir 是标注文件目录img_dir 是原图目录两者要对应上。跑完如果输出为空说明这批标注基本干净可以进入训练流程。如果有问题根据提示逐条修别带着脏数据去训模型否则 loss 曲线会教你做人。4. 避坑与排查标注工具用不对模型白训一半4.1 启动报错 “No module named ‘libs.resources’”现象在源码目录直接 python labelImg.py提示找不到 libs.resources 模块。 原因labelImg 的界面资源文件需要先编译成 Python 模块源码包里带的是 .qrc 文件不是 .py。 解决在源码根目录执行pyrcc5 -o libs/resources.py resources.qrc前提是 PyQt5 装好了。如果提示 pyrcc5 找不到用python -m PyQt5.pyrcc_main代替。4.2 标注文件保存位置不对训练时找不到现象画完框点保存提示保存成功但训练脚本读不到标注。 原因labelImg 默认把标注存到图片同级目录如果你没手动 Change Save Dir它不会自动建子文件夹。 解决启动后第一件事就是 Change Save Dir指定一个独立目录。另外注意YOLO 格式下labelImg 会在保存目录下生成 classes.txt这个文件记录了类别顺序训练时要用到别删。4.3 中文路径导致图片加载失败现象Open Dir 选了带中文的文件夹文件列表是空的或者图片显示不出来。 原因Qt 在部分系统上对非 ASCII 路径支持不好尤其是 Windows 下。 解决把图片和标注都放在纯英文路径下比如 D:\datasets\project_a\images。如果已经标了一半把整个目录改名再重新打开标注文件里的 filename 字段也要同步改否则校验脚本会报图片不存在。4.4 快捷键冲突导致画框中断现象按 W 没反应或者画到一半框消失了。 原因输入法没切到英文状态W 被当成中文输入了。或者焦点在右侧标签列表上快捷键不生效。 解决标注前把输入法切成英文鼠标点一下中间画布区域再按 W。如果还是不行检查是不是开了某些全局快捷键软件把 W 占用了。4.5 大图片加载卡顿甚至崩溃现象打开几千像素的大图界面卡死或者直接闪退。 原因labelImg 默认会把整张图加载到内存渲染图片太大时 Qt 的渲染压力扛不住。 解决标注前先把图片缩放到合理尺寸比如长边不超过 2000 像素。用 OpenCV 批量缩放一下再拿去标。缩放后坐标会变但如果你是在缩放后的图上标训练时也用同样尺寸那就没问题。5. 进阶技巧用脚本批量转换格式与自动预标注5.1 Pascal VOC 转 YOLO 格式的批量脚本很多团队一开始用 labelImg 标的是 VOC 格式后来换训练框架需要 YOLO 格式手动转不现实。下面这个脚本可以批量转换核心逻辑是读 XML 里的绝对坐标除以图片宽高做归一化import os import xml.etree.ElementTree as ET from PIL import Image def voc_to_yolo(anno_dir, img_dir, output_dir, class_list): # class_list 是类别名列表顺序要和训练时一致 class_map {name: idx for idx, name in enumerate(class_list)} for xml_file in os.listdir(anno_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(anno_dir, xml_file)) root tree.getroot() # 获取图片尺寸 img_name root.find(filename).text img_path os.path.join(img_dir, img_name) with Image.open(img_path) as img: w, h img.size lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in class_map: continue # 跳过未定义的类别 cls_id class_map[cls_name] bbox obj.find(bndbox) xmin float(bbox.find(xmin).text) ymin float(bbox.find(ymin).text) xmax float(bbox.find(xmax).text) ymax float(bbox.find(ymax).text) # 归一化并计算中心点和宽高 cx (xmin xmax) / 2.0 / w cy (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) # 写入同名 txt 文件 out_path os.path.join(output_dir, xml_file.replace(.xml, .txt)) with open(out_path, w) as f: f.write(\n.join(lines)) # 用法 voc_to_yolo(./annotations, ./images, ./labels, [person, car, dog])参数说明class_list 必须和训练时的类别顺序完全一致否则索引对不上。归一化保留 6 位小数足够YOLO 官方也是这个精度。转换完记得抽查几个 txt看看坐标是不是在 0 到 1 之间超出范围说明原 XML 里的框有越界。5.2 用预标注模型减少手工画框如果你要标几千张图纯手工画框效率太低。常见做法是先用一个已经训好的模型跑一遍推理把预测框导出成 VOC 或 YOLO 格式再用 labelImg 打开这些预标注文件人工只做修正。labelImg 支持加载已有的标注文件你只要把预标注的 XML 放到和图片同名的路径下打开图片时框会自动显示出来。具体流程用 YOLOv8 推理一批图导出成 VOC 格式的 XML然后把这些 XML 放到 annotations 目录图片放 images 目录启动 labelImg 后 Open Dir 选 imagesChange Save Dir 选 annotations它就会自动读取同名 XML 并渲染框。你只需要拖动调整不准的框删掉误检的补上漏检的。这样效率能提升三到五倍尤其是类别少、场景固定的数据集。5.3 验证标注质量的一个笨办法但有效标完一批数据别急着训。随机抽 20 张图用脚本把标注框画到原图上生成可视化结果肉眼过一遍。下面这段代码用 OpenCV 画框import cv2 import xml.etree.ElementTree as ET import os def draw_boxes(img_path, xml_path, output_path): img cv2.imread(img_path) tree ET.parse(xml_path) root tree.getroot() for obj in root.findall(object): name obj.find(name).text bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2) cv2.putText(img, name, (xmin, ymin - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) cv2.imwrite(output_path, img) # 批量可视化 for xml_file in os.listdir(./annotations): if xml_file.endswith(.xml): img_file xml_file.replace(.xml, .jpg) draw_boxes(f./images/{img_file}, f./annotations/{xml_file}, f./vis/{img_file})跑完打开 vis 文件夹一张张翻。重点看三类问题框有没有把目标截断、类别有没有标错、密集区域有没有漏标。这个步骤花不了多少时间但能拦住大部分低级错误。从那以后我每次标完新数据都强制走一遍可视化抽检宁可多花半小时也不想训到一半发现标签有问题再回头返工。希望帮到你。本文还有配套的精品资源点击获取