资讯动态

labelImg图像标注工具全指南:安装、标注实操与格式转换

发布时间:2026/10/21 3:58:31 来源:尧图企业网站定制
简介LabelImg 是一款可视化的图像标注工具源码包面向需要自制目标检测数据集的算法工程师与深度学习者常用于 Faster R-CNN、YOLO、SSD 等模型的训练前标注。使用时需配置 python lxml 环境标注结果自动生成 PASCAL VOC 格式的 XML 文件便于直接接入主流检测框架减少数据预处理成本。压缩包共 127 个文件、约 6.39MB其中 44 个 Python 脚本构成核心逻辑38 张 PNG 图片与 JPG、SVG 文件提供示例与界面图标另有 shell 脚本、配置文件、qrc 资源描述及说明文档等项目结构完整便于离线查阅和二次开发。目前已有 357 人浏览学习。对无法访问 GitHub 的开发者来说这份源码省去了外网下载不便解压即可查看 1.8.1 版本完整实现借助 demo 图片快速上手标注流程也可以按需修改界面、扩展标注功能或集成到自己的训练流程中。1. 图像标注工具选型为什么老项目里总还留着 labelImg做计算机视觉项目数据标注是绕不开的第一道工序。labelImg 这种老牌开源标注工具界面朴素但功能完整支持 PascalVOC 和 YOLO 两种主流标注格式代码全开放、可随意改直到今天我依然把它当作本机标注的首选工具。它解决的核心问题很直接给你一套不需要联网、不依赖在线平台的本地标注方案适合需要自己准备数据集的入门学习者和中小型项目团队。这篇笔记从源码包拆解出发讲清楚安装启动、标注实操、格式转换和踩坑点让新手能照做让熟手能少走弯路。2. 安装与启动从 labelImg-master 源码包到成功打开界面2.1 源码目录里到底有什么把 labelImg-master.rar 解压后首先应该看清目录结构不要急着双击运行。整个项目的核心代码量不大但文件布局有它的逻辑。labelImg-master/ ├── labelImg.py # 主入口GUI 逻辑全在这 ├── labelImg.pyw # Windows 无控制台窗口的启动器 ├── libs/ # 核心库包含画框、数据格式处理等 │ ├── canvas.py # 画布模块负责矩形框绘制和编辑 │ ├── pascal_voc_io.py # PascalVOC XML 格式读写 │ ├── yolo_io.py # YOLO TXT 格式读写 │ └── ... ├── data/ │ ├── predefined_classes.txt # 预定义标签列表 │ └── ... ├── resources.py # Qt 资源文件编译后的模块 ├── requirements.txt # Python 依赖列表 └── setup.py # 安装脚本这里最值得关注的是libs/目录下的格式读写模块。pascal_voc_io.py负责 XML 格式的解析与保存yolo_io.py负责 YOLO 格式的转换。如果你后期想要扩展新的标注格式直接在这两个模块旁边加一个xxx_io.py然后在主程序中注册即可。2.2 依赖安装三步让环境跑起来labelImg 是基于 PyQt 的图形界面工具核心依赖只有两个PyQt5 和 lxml。不同操作系统下安装方式略有差异但思路一致。# Linux/macOS 环境 pip install pyqt5 lxml # Windows 环境建议用 pip 安装完整依赖 pip install -r requirements.txtrequirements.txt文件里列出了所有依赖项直接安装即可。需要注意 PyQt5 的版本兼容性我遇到过在特定 Python 版本下 PyQt5 安装失败的情况一般升级到最新的 PyQt5 就能解决。依赖装完后启动方式有两种。在终端里运行python labelImg.py会附带控制台输出方便排查问题双击labelImg.pyw则不会弹出黑色控制台窗口。# 推荐首次运行时用这个命令能看到完整的调试信息 python labelImg.py启动后出现主窗口就说明环境没问题了。如果你在 Windows 上遇到 DLL 加载失败的报错多半是 PyQt5 安装不完整重装一次即可。2.3 启动参数直接打开图片目录和预定义标签labelImg 支持在启动时传入参数直接用命令行打开图片文件夹和标签文件省去每次手动加载的步骤。# 格式labelImg.py [图片路径] [预定义类别文件路径] python labelImg.py ./images ./data/predefined_classes.txt第一个参数是图片文件夹路径第二个参数是预定义标签文件路径。启动后自动加载指定图片目录标签列表也会同步填充。这一步在实际项目中非常实用尤其是数据集分布在多个文件夹时可以写脚本批量调用不同参数。注意路径不要带中文虽然某些版本支持中文路径但那属于玄学范畴我通常在项目初始化阶段就把所有路径统一成英文避免后面训练时各种诡异报错。3. 标注实操画框、快捷键、类目管理与保存格式3.1 界面布局和标注主流程labelImg 主界面由菜单栏、左侧工具区、中间画布和右侧标签列表组成。打开一张图片后按W键进入画框模式在目标物体上按住鼠标左键拖拽松手后弹出类别选择框选择或输入类别即可。一个完整的标注流程是加载图片 → 画框 → 选类目 → 保存 → 切换到下一张不断重复。画框时尽量贴合目标边界不要留太多背景也不要切掉目标边缘这两点直接影响后续检测模型的训练效果。右侧的标签列表会展示当前图片所有标注框。如果某个框画歪了选中后可以直接拖动边缘调整如果需要删除按CtrlR或者右键菜单删除。3.2 快捷键标注效率的核心差距标注工作重复性极高用鼠标点菜单的效率远低于快捷键。我整理了一份高频快捷键表熟练后标注速度能提升一倍以上快捷键功能使用场景W创建矩形框画新标注框A / D切换上一张/下一张图片连续标注时快速切换CtrlS保存标注结果手动保存当前图片标注CtrlD复制当前标注框同类物体密集出现时CtrlR删除当前选中框画错或框选不当时Del删除选中的标注框同上CtrlZ撤销上一步操作误拖动或误删除这里特别说下CtrlD复制框的功能。当一张图里有大量同类物体时画完第一个框后用复制功能生成新框再移动到目标位置比重新画框快得多。不过复制出来的框默认位置相同需要手动拖到目标位置。另一个容易忽略的是缩放功能鼠标滚轮缩放画布按住空格键拖动画布。标注大图时先整体画完所有框再局部放大微调边界效率最高。我见过某开发者朋友全程用 100% 缩放逐像素抠框一个下午只标了 20 张图这是典型的工具使用不当。3.3 保存在哪里PascalVOC、YOLO 和 ImageNet保存格式可以在菜单栏的PascalVOC和YOLO之间切换默认是 PascalVOC 格式。这两种格式本质区别在于标注数据的表达方式PascalVOC 格式每张图片对应一个同名的 XML 文件里面记录了图片尺寸、通道数和每个标注框的类别及坐标信息。YOLO 格式每张图片对应一个同名的 TXT 文件每行一条记录格式为类别ID 中心点x 中心点y 框宽度 框高度所有坐标值都归一化到 0~1。实际项目中如果模型框架用的是 YOLO 系列就要选 YOLO 格式保存如果用 Faster R-CNN 或 SSD一般选 PascalVOC。切换格式的方法是在菜单栏点击PascalVOC或YOLO菜单项当前格式会在标题栏显示。这里有个坑在后面单独说YOLO 模式保存出的坐标是归一化后的浮点数XML 里存的是整数像素值两者不是简单的字段改名关系格式转换时要注意换算逻辑。4. 格式转换实战VOC XML 批量转 YOLO TXT 的脚本4.1 为什么要自己写转换脚本虽然 labelImg 支持直接保存 YOLO 格式但实际使用中很多人拿到的标注数据是 PascalVOC 格式的而模型框架只认 YOLO 格式或者反过来。每次重新标注不现实手写转换脚本是最高效的方式。还有一个更现实的情况多人协作的数据集可能混用了两种格式统一处理时必须用脚本批量转换。我一般是先写一个通用转换脚本把所有数据集中到一个目录再统一格式。4.2 核心脚本XML 解析与归一化计算转换逻辑分三步读取 XML 文件、解析每个标注框的坐标、计算归一化后的转换结果并写入 TXT。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, output_dir, class_names): 将单个 PascalVOC XML 文件转换为 YOLO TXT 文件 :param xml_path: 输入 XML 文件路径 :param output_dir: TXT 输出目录 :param class_names: 类别名称列表用于映射类别ID tree ET.parse(xml_path) root tree.getroot() size root.find(size) width int(size.find(width).text) height int(size.find(height).text) base_name os.path.splitext(os.path.basename(xml_path))[0] txt_path os.path.join(output_dir, base_name .txt) lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_names: print(f跳过未知类别: {name} 在 {xml_path}) continue class_id class_names.index(name) bndbox obj.find(bndbox) xmin float(bndbox.find(xmin).text) ymin float(bndbox.find(ymin).text) xmax float(bndbox.find(xmax).text) ymax float(bndbox.find(ymax).text) # 计算 YOLO 需要的中心点和宽高并归一化 center_x (xmin xmax) / 2.0 / width center_y (ymin ymax) / 2.0 / height box_width (xmax - xmin) / width box_height (ymax - ymin) / height lines.append(f{class_id} {center_x:.6f} {center_y:.6f} {box_width:.6f} {box_height:.6f}) with open(txt_path, w, encodingutf-8) as f: f.write(\n.join(lines) \n) print(f已转换: {os.path.basename(xml_path)} - {os.path.basename(txt_path)})逻辑说明代码先解析 XML 里的图片尺寸这是坐标归一化的分母然后遍历每个 object 节点获取类别名和 bndbox 子节点里的四个边界坐标。归一化计算中中心点坐标等于 (xminxmax)/2 再除以图像宽度或高度框的宽高等于 (xmax-xmin) 除以图像宽度。最终写入 TXT 时浮点数保留 6 位精度够用且文件不会太大。参数说明class_names列表的顺序必须和模型训练时的类别顺序一致。常见做法是先扫描全部 XML收集所有类别并按字典序排序再生成映射表。如果不一致训练时类别就乱了。批量处理时加一个外层遍历def batch_convert(xml_dir, output_dir, class_names): 批量转换一个目录下的所有 XML 文件 os.makedirs(output_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if xml_file.endswith(.xml): voc_to_yolo( os.path.join(xml_dir, xml_file), output_dir, class_names )4.3 转换后的验证方式转换不是跑完就结束必须抽样验证结果。最简单的方式是用 labelImg 打开转换后的目录切到 YOLO 模式一张张看标注框是否贴合目标。还可以写个校验脚本检查坐标是否越界import os def validate_yolo(txt_path, img_width, img_height): 检查 YOLO 标注是否越界 :param txt_path: TXT 文件路径 :param img_width: 图片宽度 :param img_height: 图片高度 with open(txt_path, r) as f: for line_num, line in enumerate(f.readlines(), 1): parts line.strip().split() if len(parts) ! 5: print(f格式错误: {txt_path} 第{line_num}行) continue _, cx, cy, w, h parts cx, cy, w, h float(cx), float(cy), float(w), float(h) # 还原像素坐标 abs_x1 (cx - w / 2) * img_width abs_y1 (cy - h / 2) * img_height abs_x2 (cx w / 2) * img_width abs_y2 (cy h / 2) * img_height if abs_x1 0 or abs_y1 0 or abs_x2 img_width or abs_y2 img_height: print(f越界: {txt_path} 第{line_num}行 [{abs_x1:.1f},{abs_y1:.1f},{abs_x2:.1f},{abs_y2:.1f}])越界通常意味着原 XML 的坐标超出图片边界这类文件在训练时会报错或被框架丢帧提前发现能省下不少排查时间。5. 避坑与常见问题五个最常翻车的点5.1 现象打开图片程序直接闪退或崩溃原因有两个最常见的是图片路径包含中文PyQt 自带的文件读取模块在处理非 ASCII 路径时不稳定其次是 PyQt5 和 Python 版本不匹配导致的底层错误。解决把整个项目的路径统一改成英文从根目录到图片文件夹都不要有中文。或者看报错代码如果是could not decode to unicode类的错误就是路径问题。换用虚拟环境安装最新版 PyQt5 能解决绝大多数版本兼容问题。5.2 现象图片可以打开但画不了框鼠标拖拽无反应原因当前标注工具还停留在编辑模式没有进入创建模式或者上一次软件异常退出导致画布状态卡死。解决按一下键盘上的W键切换到创建模式看光标是否从箭头变成十字。如果W键无效重启程序并检查菜单栏里的 Edit 模式是否被误勾选。这个坑多发生在快速连续操作时画完一张图马上切下一张画布还没重置就按鼠标。5.3 现象YOLO 模式下保存的 TXT 文件内容错乱坐标出现大于 1 的数原因labelImg 的 YOLO 模式写入采用的是归一化坐标但如果你手工修改过 XML或者在部分版本里切换格式时没有重新加载图片程序可能仍按旧逻辑输出。解决切换保存格式后必须重新打开图片目录再继续标注。修改 XML 文件后要彻底关闭再启动 labelImg确保配置缓存刷新。输出结果可以用 4.3 节的校验脚本检查坐标越界就说明转换逻辑有问题。5.4 现象大图标注卡成幻灯片拖动一条线都要等一秒原因高分辨率图片载入 GUI 时会全量加载像素数据内存和 GPU 没有足够的缓冲空间。解决降低图片预览分辨率在视图菜单里把缩放比例调到 50% 或 25%画框时用的是相对坐标不影响最终保存的精度。另一个方法是把图片在标注前先压缩到 2000 像素以内模型训练时候再恢复原尺寸这样标注流畅度提升明显。5.5 现象标注了一下午关掉软件后 XML 文件全是旧的原因labelImg 默认是手动保存如果不点保存直接切换图片或退出当前图片的标注数据不会写入文件。这个坑几乎每个新手都踩过。解决养成强制保存的习惯每标完一张图就按CtrlS或者把菜单栏的自动保存选项勾上。自动保存模式下切换图片时自动写入 XML不会丢数据。但从那以后我每次标注大数据集前都先开启自动保存再手动保存一次确认输出目录可写双保险才安心。6. 进阶技巧预定义标签、自动保存与备份习惯自定义标签列表是提升标注效率的关键一步。data/predefined_classes.txt文件里每行一个类别名软件启动时会读取这些类别。你只需要编辑这个文件填入当前项目的全部目标类别标注时就不用每次手敲类别名了# data/predefined_classes.txt 示例 person car bicycle traffic_light启动命令加上类别文件路径后点击类别选择框会直接出现下拉列表点一下就能完成选择比手敲拼音快得多。类目命名建议统一用英文小写加下划线不要混用中文和英文否则后续训练框架处理类别映射时会很痛苦。自动保存功能在视图菜单里勾选。开启后切换图片或关闭程序前当前标注自动写入 XML。我一般还会定期备份标注文件到独立目录# 简易备份脚本每小时执行一次 cp -r ./labels ./backup_labels_$(date %Y%m%d_%H%M)标注工作最怕的不是标错而是标错后没有后悔药。开启自动保存固然方便但保存间隔内如果软件崩溃最近几张图的标注还是会丢。我习惯每标完一批就手动备份一次标注目录已备不时之需。最后分享个人习惯拿到一批新标注数据先抽样打开五六个 XML对照着图片看坐标与标注框是否一一对应跑一遍格式转换脚本再检查转换结果。这套流程走完后才把数据交给训练脚本避免训练到一半才发现数据格式有问题。希望这套工具与流程能帮你在标注环节节省一点时间把精力放在模型本身。从那以后我每次拿到新数据集都强制走一遍预定义标签确认 → 自动保存开启 → 抽样检查坐标 → 转换脚本验证的完整流程标注翻车率降了很多希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑