新闻详情

新闻详情

首页 / 资讯中心 / 详情

labelImg实战教程:图像标注工具部署、使用与YOLO格式转换

发布时间:2026/9/26 12:07:53来源:尧图网络
labelImg实战教程:图像标注工具部署、使用与YOLO格式转换
简介图像标注工具LabelImg是一款开源、高效的标注软件专为计算机视觉中的目标检测与实例分割任务而设计解决了人工标注图像边界框和多边形耗时耗力的问题。这份压缩包提供了该工具的完整源代码、项目配置和图形资源面向需要批量处理图像数据的研究人员、算法工程师和学生可用于快速生成符合PASCAL VOC等标准的XML标注文件。资源共118个文件压缩包大小约6.95MB核心为27个Python源文件同时包含38个PNG图标、SVG矢量图、Shell启动脚本、Markdown文档以及安装脚本、配置文件、Makefile等工程化构建工具支持Windows、Linux和macOS多平台。目前已有704人学习下载适合希望了解标注工具内部实现、参与开源项目或进行二次开发的读者。深入研读主程序与资源管理模块可以掌握界面交互逻辑、文件组织方式和打包构建全流程为搭建自定义标注流水线或扩展标注功能提供直接参考。1. labelImg是什么做目标检测绕不开的免费标注工具我研究生阶段第一次跑目标检测实验导师丢过来两百多张配电柜的现场照片让我“先标出来”。当时我用画图工具一张张框框到第11张就彻底崩溃了——不是觉得累是意识到这么标的坐标根本没法用。后来用了labelImg这个工具才发觉之前一周的笨功夫别人半天就能干完。labelImg是一个用Python写的图形化图像标注工具界面基于PyQt5功能纯粹打开图片目录鼠标画矩形框填入类别名保存成PascalVOC格式的XML或YOLO格式的txt。它解决的就是目标检测落地前最耗时最枯燥的数据准备环节适合刚入门的小白也适合要快速产出小批量验证样本的算法工程师。这个工具不需要训练、不需要显卡解压即用上手成本在标注工具里几乎是最低的。2. 从压缩包到可运行Windows与Ubuntu两条部署路径拿到手的「labelImg-master图像标注工具.zip」解压后本质上是整个项目的源码仓库。目录结构很典型根目录下的labelImg.py是主程序libs/目录放着界面控件和画框逻辑data/目录里有预定义类别文件predefined_classes.txt资源文件是resources.qrc。这是一个标准Python应用不需要编译安装部署的本质就一件事把PyQt5和lxml两个第三方依赖装好然后让Python能拉起主程序。很多人在这一步就翻车是因为把“解压”当成了“安装”双击py文件没反应就以为包坏了。实际上labelImg的运行逻辑是解释执行不是安装式启动。搞清楚这一点后面所有报错都能顺着“环境变量→依赖缺失→解释器版本”这条线去查。2.1 Windows下的安装依赖顺序与两个常见启动报错Windows上我最推荐的做法是先建虚拟环境再装依赖。不要图省事直接pip install到全局Python尤其开发机上同时装了Anaconda和官方Python的情况两个解释器抢PATH装完依赖后根本不知道被哪边接管。我在新机器上的固定操作序列是cd labelImg-master python -m venv venv venv\Scripts\activate pip install PyQt55.15.6 lxml4.9.1 python labelImg.py第一步进入解压后的源码目录第二步创建的venv是一个独立的Python环境所有依赖只装在这个目录里不污染系统解释器第三步是Windows下的激活语法激活后终端提示符前面会出现(venv)第四步我用等号锁了版本号——PyQt5锁定5.15.6是因为5.15.7之后在部分Windows高分辨率缩放设置下出现过按钮错位lxml锁定4.9.1是为了避开新版在Python 3.10上偶发的解析崩溃最后一步直接以脚本方式启动GUI。如果报「ModuleNotFoundError: No module named PyQt5」几乎都是开了新终端后忘了重新激活虚拟环境。注意PowerShell和CMD对激活命令的支持程度不一样CMD里一定要先执行activate再跑python。如果报错是lxml缺失补pip install即可。还有一个特别常见的现象在文件管理器里双击labelImg.py结果弹出了记事本窗口——这是Windows把.py文件关联到了编辑器不是程序坏了正确姿势是在终端里手动执行。如果机器上有Anaconda我建议换一条路conda create -n labelimg python3.8然后pip install PyQt5 lxml。Python 3.8是我试过兼容性最稳的版本3.10以上偶发和旧版PyQt5不兼容的情况。这样整条链路最干净以后卸载也不会留垃圾。2.2 Ubuntu 18.04上的部署apt装依赖与源码启动的排查顺序在Ubuntu 18.04上部署labelImg是另一套逻辑。系统自带的Python 3.6比较旧apt源里也没有pip版PyQt5那么激进所以最稳的组合是让apt装Qt界面库pip只补lxml这一个解析库。我在Ubuntu 18.04上的命令序列sudo apt install python3-pyqt5 -y python3 -m pip install lxml4.9.1 --user cd labelImg-master python3 labelImg.py第一行从apt源直接安装系统级PyQt5这是Ubuntu下最省事的方式绕开了pip在Linux上编译Qt库的一堆坑第二行的--user参数解决权限问题第三行进目录第四行启动。注意这里不要再执行pip install PyQt5否则会和系统自带库重复运行时可能出现动态库装载冲突。如果在桌面环境下双击没反应我的排查顺序有固定套路先echo $DISPLAY看有没有输出——通过SSH远程连服务器时这个变量通常是空的GUI程序起不来解决方法是回到物理终端执行或者手动export DISPLAY:0再确认python3指向谁如果which python3显示的是Anaconda路径而Anaconda环境里又没装PyQt5就会报无模块错误此时要么进conda环境补装要么把启动命令换成/usr/bin/python3 labelImg.py。Linux下还有一个源码编译相关的坑如果你从GitHub拉的代码比较新直接跑可能会在资源加载时报AttributeError提示libs.resources里缺属性。这是因为新版代码改了图标资源但没有用Qt的编译工具重新生成resources.py。解决方式是在根目录执行pyrcc5 -o libs/resources.py resources.qrc这个命令把qrc资源文件编译成Python模块labelImg在导入时才能找到对应的图标和样式。如果提示pyrcc5命令不存在说明缺少PyQt5的开发工具包apt install pyqt5-dev-tools装一下即可。3. 亲手标注一版数据操作拆解与格式落地部署跑通只是起点真正决定标注效率的是工作流。很多人把labelImg当画框软件用打开、框选、保存然后抱怨慢。实际上它内置了一套以键盘为主的操作体系配合合理的目录规划一小时标两百张图完全可行。这一章我把一个完整标注项目的操作细节、快捷键和产物格式全部拆开讲。3.1 新建标注工程目录结构、预定义类别与一张图的完整标注动作拿到一批待标注图片后先别急着打开labelImg。按我习惯先建立这样的目录结构project/ images/ # 原始图片jpg或png annotations/ # 标注产物XML文件 classes.txt # 类别清单一行一个图片文件名里不要带中文和空格也不要放在带中文的路径下。这不是洁癖而是labelImg的XML保存逻辑在部分Windows环境下对非ASCII路径处理不稳定中文路径轻则保存报错重则闪退。启动labelImg后默认界面顶部是菜单栏左侧是工具栏中间是图片显示区。第一次用需要先做两件事在菜单Edit里选「Open Dir」打开images目录再点「Change Save Dir」把保存目录指定为annotations。很多人只开了图片目录、没改保存目录最后发现XML不知道存哪了。画框的完整动作是按键盘W键进入画框模式在目标左上角按住鼠标左键拖到右下角松开弹窗里输入类别名回车确认。一个目标框完按D键切到下一张继续画。一个标注样本的产出就是这么朴素——不需要在工具栏上点来点去。类别名第一次输入后会被记录到predefined_classes.txt但要注意这个文件只有在「保存目录」指定的位置才能自动创建和更新。如果你在项目中后期发现类别名总是别名检查一下是不是多个项目共用了同一个predefined_classes.txt。3.2 快捷键与批量操作效率差距在这里拉开观察一下标注效率高的人你会发现他们的鼠标几乎只用来框目标其余操作全在键盘上。labelImg默认快捷键里最核心的几个我直接列成表快捷键作用使用场景W进入画框模式每张图开始前按一次D / A下一张 / 上一张批量切换图片CtrlS保存当前XML每张图画完按一次CtrlE编辑当前框类别名框错类、想改类时Del删除当前选中框框歪了、框多了CtrlZ撤销画框过程中的最后一步画到一半手抖空格标记当前图为已标注跳过某张图时做状态记录Ctrl滚轮缩放图片小目标看不清时这里有两个操作习惯建议。第一保存要勤快我的节奏是一张图画完立即CtrlS再按D去下一张养成肌肉记忆后不会漏存第二当一张图里目标很多时每框完一个类别就顺手回车不要让弹窗停留太久弹窗挂着的时候快捷键是失灵的。还有一个隐藏功能菜单View里有「Auto Labeling」和「Single Class Mode」。Single Class Mode开启后多个目标框都沿用当前类别名不再弹输入框适合一张图里同一个类别出现很多次的场景能省掉一半时间。Auto Labeling适合配合辅助模型做预标注属于进阶玩法后面章节单独讲。3.3 保存成什么PascalVOC XML的结构与坐标含义labelImg默认输出PascalVOC格式的XML文件一张图对应一个同名XML。这个格式本身就是目标检测领域最通用的标注存储格式所以它也是一张“图纸”后续转YOLO、转COCO都要基于它。一个典型的XML长这样annotation folderimages/folder filenameimg_001.jpg/filename pathD:/project/images/img_001.jpg/path sourcedatabaseUnknown/database/source size width1920/width height1080/height depth3/depth /size object namehelmet/name bndbox xmin100/xmin ymin120/ymin xmax400/xmax ymax380/ymax /bndbox /object /annotation关键是size和object两段size里的width、height、depth记录图片原始尺寸object里的bndbox记录目标的左上角和右下角坐标。注意这个坐标是相对原始图片的像素坐标不是归一化的。后续做模型训练时不管是转YOLO还是转COCO都要靠这两个信息做换算。如果一张图里有多个目标XML里就会有多个object块。还有一个容易被忽略的点标注框超出图像边界时labelImg不会自动修正xmin可能大于width这类脏数据进去训练模型会直接报错或导致loss异常所以标注环节就尽量框在边界内。4. labelImg避坑指南闪退、乱码、漏标这些坑我都踩过用labelImg的时间久了踩过的坑能写一张纸。这一章挑我遇到最多、也最影响进度的五个问题按「现象→原因→解决」的方式记录下来。很多问题在网上搜半天找不到答案其实原因简单得让人无语。4.1 画框到一半闪退一整天白干现象图片加载正常但只要鼠标开始拖框或者拖到一半按了右键程序直接消失连报错弹窗都没有。Windows上重启后再打开发现刚才没保存的标注全丢了。原因两个最普遍的源头。一是图片路径或文件名里有中文、特殊符号Qt在保存XML或者绘制图像时触发编码异常直接退出二是单张图片分辨率过高比如动辄6000x4000的航拍图labelImg的绘制组件在拖框过程中内存暴涨被系统杀掉了。解决图片统一改名成纯英文数字路径不要放中文目录高分辨率图先缩放到2000像素边长以内再标注标注完用原始分辨率训练时再按坐标比例换算回去操作上要养成每张图CtrlS的习惯这样就算闪退也只丢一张。4.2 XML里中文类别名乱码现象类别名输入中文后保存的XML文件用记事本打开是乱码或者保存时直接报UnicodeEncodeError用网上的XML转VOC脚本解析时直接报错。原因labelImg的master分支在Python 3下默认用UTF-8处理字符串但如果用的是旧版源码、或者lxml版本太老编码处理会退化。还有一个隐藏因素Windows下输入法输入中文时Qt的弹窗控件偶发把字符状态搞乱。解决最省心的是类别名直接用英文比如helmet、person、defect训练时再在脚本里做category_map映射成中文标签显示。如果一定要用中文就把lxml升级到4.9.1以上并且在labelImg.py开头强制加上# -- coding: utf-8 --声明然后重新启动。4.3 Qt资源编译报错启动即崩溃现象从GitHub拉最新的labelImg代码在Ubuntu上执行python3 labelImg.py启动瞬间报AttributeError日志末尾有libs.resources相关字样或者界面按钮上全是空白的占位符图标不显示。原因新版源码修改了resources.qrc里的资源引用但仓库里没有附带编译好的resources.py。labelImg在导入时执行qInitResources()找不到对应属性整个模块初始化失败。解决按第二章的方法重新pyrcc5编译资源文件编译完确认libs目录下生成了resources.py再启动就正常了。MacOS用户注意pyrcc5在Qt5的环境里一般自带如果命令找不到检查是否完整安装了PyQt5。4.4 复杂背景下漏标小目标现象图片里目标小而密集或背景纹理和目标颜色接近时标注完总觉得框全了跑出来的模型却漏检严重复盘才发现大量小目标根本没框。原因这不是labelImg的故障是人的视觉盲区。屏幕上目标小到一定程度人眼扫过就是会漏。高强度连续标注时注意力还会随疲劳下降。这个坑比软件bug更隐蔽因为没人会怀疑自己漏标。解决我一般标完一轮后会强制休息几分钟再看第二遍只看自己第一遍可能漏的区域也可以让另一个人交叉复核同一批图。更工程化的做法是用一个小脚本把每个类的实例数量统计出来如果某些类数量异常少就重点复查对应图片。脚本写法在第六章给出来。4.5 删错框没有后悔药现象鼠标点选框后按Del框直接消失想撤销却怎么按CtrlZ都没反应原来标好的目标只能重新画。原因labelImg的撤销机制只覆盖画框过程中的节点操作对已经确认的框执行删除后是不进撤销栈的。习惯性按CtrlZ是文本编辑器的肌肉记忆在labelImg里并不总是有效。解决点选框之前先确认是不是当前选中了正确的框框被选中时边框会明显高亮删除前宁可先按CtrlE看一眼类别再按Del。我自己的习惯是每隔五张图关闭并重新打开一下当前XML确认最近的删除操作没有误伤到上一张的标注。5. 把VOC格式转成YOLO格式坐标换算与按类别拆分labelImg的XML格式虽然通用但当前主流检测模型YOLOv5、YOLOv8的标注输入是纯文本的txt格式每行一条记录类别编号、目标中心x、目标中心y、目标宽度w、目标高度h全部相对图片尺寸归一化。所以拿到一批XML后第一件事就是把它们转成YOLO标签。这一步用脚本批量做比手工在labelImg里切格式靠谱得多。5.1 两种坐标体系的换算关系VOC的XML里存的是绝对坐标——目标左上角(xmin, ymin)和右下角(xmax, ymax)。YOLO格式需要的是相对坐标——目标中心点(x_center, y_center)和宽高(w, h)且取值范围在0到1之间。换算公式是x_center (xmin xmax) / 2 / image_width y_center (ymin ymax) / 2 / image_height w (xmax - xmin) / image_width h (ymax - ymin) / image_height注意两个边界问题一是XML里如果目标框越界算出来的中心点可能落在图像外面或宽高超过1这种值喂给模型会直接报错二是类别名在YOLO里必须是整数编号YOLO不认字符串类名需要一个类别到编号的映射文件这就是每个项目的data.yaml里classes列表的来源。5.2 转换脚本一张图生成一个txt我每次拿到新项目的标注后都会用一个固定脚本做转换。脚本遍历XML目录逐个读坐标、做归一化、写同名txt文件。核心逻辑如下# voc_to_yolo.py # 用法: python voc_to_yolo.py xml_dir out_dir class_file import os import sys import glob import xml.etree.ElementTree as ET def convert_one(xml_path, out_dir, class_map): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt lines [] for obj in root.findall(object): name obj.find(name).text if name not in class_map: print(f跳过未知类别: {name}) continue box obj.find(bndbox) xmin int(box.find(xmin).text) ymin int(box.find(ymin).text) xmax int(box.find(xmax).text) ymax int(box.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 # 裁剪到[0,1]区间防止越界 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) w min(max(w, 0.0), 1.0) h min(max(h, 0.0), 1.0) lines.append(f{class_map[name]} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(os.path.join(out_dir, txt_name), w) as f: f.write(\n.join(lines)) if __name__ __main__: xml_dir, out_dir, class_file sys.argv[1], sys.argv[2], sys.argv[3] os.makedirs(out_dir, exist_okTrue) class_map {} with open(class_file) as f: for idx, line in enumerate(f.read().strip().splitlines()): class_map[line] idx for xml_path in glob.glob(os.path.join(xml_dir, *.xml)): convert_one(xml_path, out_dir, class_map) print(fdone: {os.path.basename(xml_path)})脚本里class_map的构建是关键classes.txt里每行一个类名行号就是YOLO里的类别编号。class_file这个参数不要传错类和编号对应关系必须和训练配置里的data.yaml一致。坐标格式保留6位小数过多的小数位不会提升训练精度反而会让文件变大。f-string里的:06f是格式化控制想改成4位精度也完全可以。5.3 按类别统计与train/val划分的批处理转完之后先别急着训练跑一个统计脚本检查标签质量。这个脚本读所有txt统计每个类别出现了多少次以及哪些txt是空的——空txt代表这张图一个目标都没标注如果它还在训练集里模型会被喂一张没有学习目标的图影响收敛。统计脚本很短:# check_labels.py # 用法: python check_labels.py label_dir class_file import os import sys import glob from collections import Counter label_dir, class_file sys.argv[1], sys.argv[2] classes [line.strip() for line in open(class_file) if line.strip()] counter Counter() empty_files [] for txt in glob.glob(os.path.join(label_dir, *.txt)): with open(txt) as f: lines [line.strip() for line in f if line.strip()] if not lines: empty_files.append(os.path.basename(txt)) for line in lines: counter[classes[int(line.split()[0])]] 1 print(类别统计:, dict(counter)) print(空标注文件数:, len(empty_files), empty_files[:10])如果某个类别的数量比预期少了一个量级回去翻一下是不是漏标了如果空文件里混进了原本有目标的图检查一下XML转txt时是不是坐标读取出了问题。train/val划分我习惯直接用命令行工具做不需要写Python。图片和标签在同一个目录的情况下按8:2随机切分ls images/*.jpg | shuf -n 100 val_images.txt这里100是验证集大小按你的总量调整。补集自动就是训练集。更稳妥的做法是用Python的random.sample因为shuf在Windows Git Bash里不一定有。划分完要确认验证集里每个类别都有样本避免出现验证集缺少某个类导致指标虚高或虚低。6. 给标注结果做量化自检一个脚本筛出漏标与错标最后一章分享一个我一直在用的收尾技巧。标注和数据转换全部完成后我不会急着训模型而是先跑一遍自检脚本把漏标和错标“打”出来。这个脚本的思路很简单统计所有txt标签文件的行数分布一组图片的目标数量如果明显少于同类其他图片大概率是漏标了同时检查类别名是否和class_file完全一致防止手滑把helmet拼成helment。脚本的核心逻辑是遍历标签目录按文件名排序对比输出目标数最少和最多的几张图再按类别做一次柱状图式的数量统计。我用的版本长这样# quality_check.py # 用法: python quality_check.py label_dir class_file import os import sys from collections import Counter label_dir sys.argv[1] class_file sys.argv[2] classes [line.strip() for line in open(class_file) if line.strip()] obj_count {} invalid [] for fname in os.listdir(label_dir): if not fname.endswith(.txt): continue path os.path.join(label_dir, fname) with open(path) as f: lines [line.strip() for line in f if line.strip()] obj_count[fname] len(lines) for line in lines: cls_id line.split()[0] if int(cls_id) len(classes): invalid.append((fname, cls_id)) sorted_files sorted(obj_count.items(), keylambda x: x[1]) print(目标数最少的前10张:, sorted_files[:10]) print(出现未知类别编号的文件:, invalid)对查出来的可疑文件回到labelImg里打开对应的图片和XML人工复核。这个动作看起来多了一步实际上能省下后面排查mAP异常的大把时间。我现在每个项目标注结束后都会跑一遍已经成了固定习惯。早期我跳过这一步直接训练结果模型在小目标上惨不忍睹最后回头查才明白是标注环节的锅——数据质量问题靠训练是救不回来的。希望帮到你少走这一段弯路。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

从零搭建 Lumerical 仿真 AI Agent:Cline + DeepSeek + MCP 教程 2026/9/26 12:53:52

从零搭建 Lumerical 仿真 AI Agent:Cline + DeepSeek + MCP 教程

Lumerical 是光子学仿真常用工具,但其脚本接口对初学者有门槛,本教程将分享如何搭建一套工具链,用自然语言指挥 AI 操作 Lumerical。 目录 一、引言 1.1 为什么写这篇教程1.2 预期效果1.3 关于 AI 控制 Lumerical 的语法正确性说明 二、适用…

阅读更多 →
Claude Code高效实践:用模板固化AI编程工作流 2026/9/26 12:53:52

Claude Code高效实践:用模板固化AI编程工作流

很多人一开始觉得 Claude Code 是个“能跑命令的聊天机器人”,用着用着发现每次都要把项目背景、代码风格、输出要求从头到尾讲一遍,特别累。后来我花了不少时间把常用的操作沉淀成一套模板,也就是 claude-code-templates,才发现这…

阅读更多 →
从“无标题”到命名:模糊项目如何落地成可执行计划 2026/9/26 12:53:51

从“无标题”到命名:模糊项目如何落地成可执行计划

“无标题”这三个字,看起来什么都没给,但恰恰是很多项目最真实的起点。无论是写一篇文章、开发一个小工具,还是启动一个全新的计划,绝大多数事情在最开始的时候都是没有名字的。名字不是起点,而是探索的结果。这篇文章…

阅读更多 →
SQL Server数据库设计实战:从表结构到索引优化的完整指南 2026/9/26 12:53:39

SQL Server数据库设计实战:从表结构到索引优化的完整指南

做SQL Server这套东西十几年,每次接手一个新项目,我第一件事不是写代码,而是先看数据库设计。很多人觉得这是小题大做,觉得CRUD嘛,表随便建一建就行了。但恰恰是这个"随便",后面会让你付出成倍的…

阅读更多 →
SQL Server数据库设计实战:从用户表到索引优化的完整指南 2026/9/26 12:53:39

SQL Server数据库设计实战:从用户表到索引优化的完整指南

1. 项目概述:别急着写表,先想清楚数据模型入行做 SQL Server 开发这么多年,我见过太多“表先建起来、业务跑着跑着再补丁”的项目,最后大多陷入字段冗余、关联混乱、查询慢到怀疑人生的泥潭。所谓数据库设计,并不是拿 …

阅读更多 →
基于小波包畸变与卷积神经网络的机械系统不平衡故障诊断方法解读 2026/9/26 12:53:39

基于小波包畸变与卷积神经网络的机械系统不平衡故障诊断方法解读

在机械系统状态监测中,实测故障样本数量往往远少于正常样本,容易导致分类模型偏向多数类而出现误诊。针对这一问题,论文《Highly imbalanced fault diagnosis of mechanical systems based on wavelet packet distortion and convolutional n…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉