☰
labelImg 图片标注工具实战:从安装到 YOLO 格式导出与避坑指南
2026/10/19 5:51:09 网站建设 项目流程

简介:LabelImg-master.zip 是一款面向计算机视觉与神经网络训练场景的开源图像标注工具源码包,适合从事目标检测、语义分割等深度学习任务的研究者、算法工程师及数据标注人员使用,可解决训练数据集制作中标注效率低、格式不统一的问题。压缩包共108个文件,约6.29MB,以27个py源码文件为核心,辅以39个png界面图标、6个svg矢量图、6个sh脚本及rst、md说明文档,另含properties、yml等配置与少量示例图片,结构完整便于二次开发。目前已有425人学习下载。资源提供直观GUI,支持矩形框、多边形等多种标注类型,标注结果可保存为XML或JSON格式并支持加载续编,兼容Windows、Mac OS与Linux,还支持自定义快捷键提升效率;随附安装说明与常见错误解决思路,帮助读者快速搭建Python环境、安装依赖并启动程序,从而高效构建高质量训练数据集。

1. 图片标注工具里的老黄牛:labelImg 到底还值不值得用

如果你正在做目标检测,手头攒了几千张图却还没标几个框,那大概率会被人安利过 labelImg。它是个用 Python + Qt 写的桌面端图片标注工具,核心功能就一件事:在图上拉框、打标签、导出成 PASCAL VOC 的 XML 或 YOLO 的 TXT。听起来朴素,但它解决的是神经网络项目里最枯燥也最要命的一环——把原始图片变成模型能吃的标注数据。labelImg-master.zip 就是它的源码包,解压即用,不依赖在线服务,不挑显卡,一台普通办公本就能跑。适合谁?刚入门目标检测、需要快速把一批图变成训练集的人;也适合那些不想被在线标注平台按张收费、想把数据留在本地的团队。下面我按实际拆包、跑通、踩坑的顺序,把这份资源讲透。

2. 拆开 labelImg-master.zip:目录结构、依赖与启动方式

拿到压缩包先别急着双击,解压后你会看到一个典型的 Python 项目目录。理解它每个文件夹干什么,后面改配置、排错才不会抓瞎。

2.1 源码目录里有什么

解压 labelImg-master.zip 后,根目录下主要包含这些内容:

路径作用
labelImg.py主程序入口,双击或命令行运行它
libs/核心逻辑,画框、读写标注、画布交互都在这里
resources/图标、样式等静态资源
data/预定义的类别文件,比如predefined_classes.txt
requirements/分版本的依赖清单,按系统选
build-tools/打包相关脚本,普通使用用不到
README.md官方说明,但版本更新后有些步骤会过时

真正要关心的只有labelImg.py、libs/和data/predefined_classes.txt。前者是入口,中间是逻辑,后者是你自定义类别的落脚点。

2.2 依赖安装:别直接 pip install 一堆

很多人翻车在第一步:直接pip install labelImg或者照着旧教程装一堆包,结果 Qt 版本冲突,窗口起不来。正确做法是先看requirements/下对应你系统的文件。以 Linux 为例,常见做法是:

# 进入解压后的目录 cd labelImg-master # 根据系统选择依赖文件,Linux 通常用这个 pip install -r requirements/requirements-linux-python3.txt # 如果上面文件不存在,用通用版 pip install -r requirements/requirements.txt

逻辑说明:requirements-linux-python3.txt里锁定了PyQt5和lxml的版本区间,避免装到不兼容的新版。参数上,如果你用 Python 3.9 以上,建议先建虚拟环境再装,否则系统里已有的 PyQt 可能把新装的覆盖掉。装完用python labelImg.py启动,能弹出窗口就说明依赖通了。

2.3 启动与界面速览

启动命令很简单:

python labelImg.py

窗口出来后,左侧是文件列表,中间是画布,右侧是标签列表和几个按钮。关键操作就几个快捷键:W画框,D下一张,A上一张,Ctrl+S保存。第一次用建议先点左侧「Open Dir」选图片文件夹,再点「Change Save Dir」选标注保存位置,然后点「Create RectBox」开始拉框。这里有个细节:保存格式默认是 PASCAL VOC 的 XML,如果你要喂给 YOLO,得在菜单里切换成 YOLO 格式,否则后面还得写脚本转,多一道手续。

3. 把标注流程跑通:从单张图到批量导出 YOLO 格式

工具能启动只是第一步,真正要落地的是「标完一批图,导出成训练脚本能直接读的格式」。这一章把完整链路走一遍。

3.1 预定义类别与快捷键配置

在data/predefined_classes.txt里一行写一个类别名,比如:

person car dog

保存后重启 labelImg,右侧标签列表就会预加载这些类别。这样标注时直接点选,不用每次手打,减少拼写不一致导致的训练报错。如果你类别多,建议按字母序排,找起来快。另外,菜单里可以开启「Auto Save Mode」,每切一张图自动保存,适合大批量标注时防止手滑丢进度。

3.2 标注操作与 XML 结构

画一个框后,labelImg 会在你指定的保存目录生成同名 XML。以一张frame_001.jpg为例,生成的frame_001.xml结构如下:

<annotation> <folder>images</folder> <filename>frame_001.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>person</name> <bndbox> <xmin>320</xmin> <ymin>210</ymin> <xmax>480</xmax> <ymax>560</ymax> </bndbox> </object> </annotation>

逻辑说明:size记录原图宽高,bndbox是左上角和右下角坐标,单位是像素。注意xmax和ymax是框的右下角,不是宽高,写转换脚本时别搞反。参数上,如果图片被旋转过,labelImg 不会自动校正,标注前最好把图统一摆正。

3.3 导出 YOLO 格式与坐标归一化

YOLO 要的 TXT 每行是类别索引 x_center y_center width height,且全部归一化到 0~1。labelImg 菜单里可以直接切换保存格式为 YOLO,切换后新保存的标注就是 TXT。但如果你已经标了一批 XML 才想起来要转,可以用下面这个脚本批量转:

import os import xml.etree.ElementTree as ET # 类别列表,顺序必须和训练时的 data.yaml 一致 classes = ["person", "car", "dog"] def convert(xml_dir, txt_dir, img_w, img_h): for xml_file in os.listdir(xml_dir): if not xml_file.endswith(".xml"): continue tree = ET.parse(os.path.join(xml_dir, xml_file)) root = tree.getroot() lines = [] for obj in root.iter("object"): cls_name = obj.find("name").text if cls_name not in classes: continue cls_id = classes.index(cls_name) bnd = obj.find("bndbox") xmin = float(bnd.find("xmin").text) ymin = float(bnd.find("ymin").text) xmax = float(bnd.find("xmax").text) ymax = float(bnd.find("ymax").text) # 归一化并转中心点格式 x_center = (xmin + xmax) / 2.0 / img_w y_center = (ymin + ymax) / 2.0 / img_h w = (xmax - xmin) / img_w h = (ymax - ymin) / img_h lines.append(f"{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}") txt_name = xml_file.replace(".xml", ".txt") with open(os.path.join(txt_dir, txt_name), "w") as f: f.write("\n".join(lines)) # 调用时传入实际图片宽高,如果尺寸不一,需要逐张读取 convert("annotations_xml", "labels_txt", 1920, 1080)

逻辑说明:脚本遍历 XML,把每个 object 的坐标按图片宽高归一化,再转成中心点加宽高的格式。参数上,classes列表的顺序必须和训练配置里的names完全一致,否则类别索引错位,模型学出来的东西全乱。如果图片尺寸不统一,得用 PIL 或 OpenCV 逐张读实际宽高,不能写死。

3.4 批量校验标注质量

标完几千张,难免有漏标或框歪的。跑训练前建议做一次快速校验:统计每张图的框数量、检查有没有宽高为 0 的框、确认类别名没有拼错。常见做法是写个脚本扫一遍 TXT,把异常文件名打印出来人工复核。这一步花十分钟,能省掉训练几小时后发现 loss 不降的后悔药。

4. 避坑与排查:labelImg 用起来最容易翻车的五个地方

这工具本身不复杂,但环境、格式、操作习惯上的坑不少。下面五条是我和身边人实际踩过的,按「现象 → 原因 → 解决」写清楚。

4.1 启动报错 Qt platform plugin 找不到

现象:命令行运行python labelImg.py,报qt.qpa.plugin: Could not load the Qt platform plugin "xcb",窗口不弹。 原因:PyQt5 装上了,但系统缺少 xcb 相关的底层库,常见于精简版 Linux 或没装图形依赖的容器环境。 解决:补装系统库,Debian 系用sudo apt install libxcb-xinerama0 libxcb-cursor0,然后重新运行。如果还不行,检查QT_QPA_PLATFORM_PLUGIN_PATH环境变量是否指向了正确的 PyQt5 plugins 目录。

4.2 标注保存后 XML 里没有 object

现象:明明画了框,保存后打开 XML 发现<object>是空的。 原因:画框后没有在弹出的小窗里输入或选择类别名,直接点了 OK 或按了回车,labelImg 认为这个框无效。 解决:画框后必须给标签,可以从右侧列表点选,也可以手动输入。开启 Auto Save 前先确认这个习惯已经养成。

4.3 图片路径含中文导致读取失败

现象:Open Dir 选了文件夹,左侧列表空白,或者图片显示为裂图。 原因:labelImg 底层用 Qt 读文件,部分版本对中文路径支持不好,尤其是 Windows 下。 解决:把图片和标注目录都改成纯英文路径,比如D:/dataset/images。这是最省事的办法,别跟编码较劲。

4.4 YOLO 格式导出后训练报类别越界

现象:训练时提示IndexError: list index out of range或类别索引对不上。 原因:labelImg 导出 YOLO 时用的类别顺序,和你在data.yaml里写的names顺序不一致。 解决:统一以predefined_classes.txt的顺序为准,导出前确认菜单里的类别列表和训练配置完全一致。转换脚本里的classes也要同步。

4.5 大图标注卡顿

现象:标注 4K 以上图片时,画布拖动明显延迟,画框跟不上鼠标。 原因:labelImg 默认会把原图缩放到画布显示,图越大,Qt 渲染开销越高。 解决:标注前先把图片统一缩到 1920 宽以内,或者换用更轻量的标注工具处理超大图。如果必须保留原图,标注时关掉「Fit Window」以外的预览选项,减少重绘。

5. 进阶技巧:用脚本把标注、校验、转换串成一条流水线

单张标、手动转,图少还行,上千张就是体力活。我后来习惯把 labelImg 当成纯标注端,后面的校验和格式转换全部脚本化,形成一条固定流水线。

5.1 标注前先统一图片尺寸和命名

在打开 labelImg 之前,先跑一个预处理脚本,把所有图片缩到统一宽度,并按类别_序号.jpg重命名。这样标注时不用来回缩放,转换时宽高也能直接用固定值,省掉逐张读图的步骤。常见做法是用 OpenCV 批量 resize:

import cv2 import os src_dir = "raw_images" dst_dir = "images" target_w = 1280 os.makedirs(dst_dir, exist_ok=True) for idx, name in enumerate(sorted(os.listdir(src_dir))): img = cv2.imread(os.path.join(src_dir, name)) if img is None: continue h, w = img.shape[:2] scale = target_w / w new_h = int(h * scale) resized = cv2.resize(img, (target_w, new_h)) cv2.imwrite(os.path.join(dst_dir, f"img_{idx:05d}.jpg"), resized)

逻辑说明:统一宽度后,高度按比例缩放,避免拉伸变形。参数target_w根据你的显存和模型输入来定,一般 1280 够用。命名用零填充序号,保证文件列表顺序稳定。

5.2 标注后自动校验并生成训练配置

标完一批,跑一个校验脚本,检查每个 TXT 的坐标是否在 0~1 之间、类别索引是否越界、有没有空文件。校验通过后,自动生成 YOLO 训练用的data.yaml:

import os labels_dir = "labels_txt" classes = ["person", "car", "dog"] # 校验 bad_files = [] for name in os.listdir(labels_dir): path = os.path.join(labels_dir, name) with open(path) as f: for line in f: parts = line.strip().split() if len(parts) != 5: bad_files.append(name) break cls_id = int(parts[0]) coords = [float(x) for x in parts[1:]] if cls_id >= len(classes) or any(c < 0 or c > 1 for c in coords): bad_files.append(name) break print("异常文件:", bad_files) # 生成 data.yaml with open("data.yaml", "w") as f: f.write(f"train: ./images\n") f.write(f"val: ./images\n") f.write(f"nc: {len(classes)}\n") f.write(f"names: {classes}\n")

逻辑说明:校验部分逐行检查字段数和数值范围,把有问题的文件名收集起来人工复核。生成配置时nc是类别数,names顺序必须和标注时一致。参数上,train和val路径按你的实际目录结构改,小数据集可以暂时用同一份。

5.3 版本管理:标注文件也要进 Git

标注数据是模型迭代的核心资产,但很多人只备份图片,忘了 XML/TXT。我一般把标注目录单独做一个 Git 仓库,每次标完一批就 commit 一次,commit message 写清楚标了多少张、改了哪些类别。这样后面模型效果波动时,能回溯到具体是哪批标注引入的问题。注意图片本身太大,用.gitignore排除,只跟踪标注文件。

从那以后我每次开新项目,都强制走一遍「预处理 → 标注 → 校验 → 生成配置」这条流水线,不再手动一张张转格式。希望帮到你。

本文还有配套的精品资源,点击获取

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

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

立即咨询