简介:面向Windows x64平台的中文汉化版labelImg 1.8.6,由作者以PyInstaller打包为绿色独立exe,下载解压后双击labelImg.exe即可直接使用,无需额外安装Python环境,适合制作深度学习目标检测数据集的新手,也方便算法工程师在本地快速完成图像标注。压缩包体积38.72MB,共151个文件,包含85个dll、30个pyd作为底层运行依赖库,23个qm为Qt语言翻译文件、支撑全中文界面显示,另有labelImg.exe主程序、Python脚本及少量配置说明,结构清晰且解压即用,不依赖系统预先部署环境。该版本经过作者实际打包与测试验证,可离线启动,标注窗口菜单、工具栏均为中文提示,免去命令行配置和依赖安装的繁琐步骤,适合Windows x64系统用户直接纳入日常标注工作流。资源当前已有1700人浏览学习,是快速获得可直接运行的汉化图像标注工具的低门槛选择。
1. labelImg 汉化版直接能跑:这个 exe 包里到底装了些什么
做目标检测数据集的朋友,对 labelImg 应该不陌生。原版项目虽然开源,但想在 Windows 上跑起来,要先装 Python、再装 PyQt5、再处理各种依赖,运气好半小时,运气不好一个下午就没了。手头这个 1.8.6 汉化中文版不一样,它把环境全部打进了 Windows x64 的 exe 里,解压出来双击即用,界面是中文的,省掉了配环境这一整段折腾。所谓直接可用,不是一句宣传,而是你拿到手就能出数据:打开图像目录,画框,保存 PascalVOC 或 YOLO 文件,直接喂给后面的训练脚本。它解决的是标注场景里最实际的问题:快速打开、框目标、落盘格式正确。适合刚接触数据标注的新手,也适合不想在工具上浪费时间的老手。
2. labelImg 1.8.6 的技术底细:PyQt5、打包原理与两种标注格式
2.1 汉化版是怎么来的:翻译文件与源码字符串
labelImg 本身是 Python 写的桌面程序,界面基于 PyQt5。1.8.6 是这个项目在社区里流传最广的版本号之一,功能完备,交互也定下来了。汉化版不是官方出的,是社区维护者改的,改法主要有两种:直接把源码里的英文字符串替换成中文后重新打包;或者走 Qt 的翻译机制,把界面文案放进 .ts 文件,再用 lrelease 编译成 .qm 给程序加载。直接改源码的汉化最彻底,菜单、按钮、对话框基本全覆盖,代价是以后升级得重新改;走 .ts 翻译路线的干净,但只能盖住调用了翻译接口的字符串,总有些右键菜单、提示框漏在外面。
这个 1.8.6 汉化版走的是前一种路线,所以主界面基本全中文,个别角落残留英文也正常,不影响使用。理解这个来源,对你判断两件事有帮助:为什么 exe 体积不小,以及杀毒软件为什么偶尔会叫。因为里面塞了一个完整的 Python 解释器和 PyQt5 运行库,用 PyInstaller 打包,体积根本压不下来。常见做法是用 PyInstaller 完成打包,命令本身能说明原理:
# 从源码重新打包 labelImg 的常见做法,理解原理用,不一定真要执行 pip install pyinstaller pyqt5 pyinstaller --windowed --onefile --name labelImg labelImg.py--windowed让程序启动时不弹黑色控制台窗口;--onefile把所有依赖打进单个 exe,代价是启动时要把内嵌资源解压到临时目录,所以第一次打开会慢一两秒;--name指定产物文件名。看到这里你基本能判断,杀毒软件对它的误报更多是特征匹配,和程序本身没有关系。
2.2 PascalVOC 与 YOLO:两种输出格式,两种使用场景
标注的本质就一句话:告诉后续训练程序,这张图里某个目标在哪个位置、属于哪一类。labelImg 支持两种输出,界面右侧的按钮负责在 PascalVOC 和 YOLO 之间切换。
PascalVOC 格式用一个 XML 文件描述一张图:文件名、图像尺寸、每个目标的类别名和边界框的四个像素坐标。XML 是人类可读的,出了错可以直接打开看,我一般拿它做前期摸索,因为处理逻辑透明。YOLO 格式用 TXT 文件描述一张图,每行一个目标,内容是类别编号加 cx、cy、w、h。cx、cy 是归一化中心点,w、h 是归一化目标宽高,全部除以图像自身宽高,取值都在 0 到 1 之间。这里最容易被忽略的一点:TXT 里只存类别编号,不存类别名,编号含义要靠一份独立的 classes.txt 去解释,序号一旦对不上,训练出来的模型类别就全乱了。
| 对比项 | PascalVOC | YOLO |
|---|---|---|
| 存储格式 | 单张图一个 XML | 单张图一个 TXT |
| 边界框 | xmin, ymin, xmax, ymax(像素) | cx, cy, w, h(归一化) |
| 类别表示 | 字符串类名 | 整数索引,靠 classes.txt 解释 |
| 常见下游 | MMDetection、Detectron2 等 | Ultralytics YOLO 系列 |
具体选哪个,取决于你要喂给谁。训练脚本明确要 YOLO 就趁标注时直接输出 YOLO,不要标完再转;只是采集数据、还没定模型,PascalVOC 更安全。labelImg 自带的转换功能,本质就是把 XML 读出来重算坐标,和后面第 4 章我给的脚本一个思路。
2.3 为什么 1.8.6 到今天还有人找
目标检测标注工具这些年出了不少,CVAT、X-AnyLabeling、Roboflow 界面都更现代。但 1.8.6 的搜索量一直没下去,原因是很多标注工程师的诉求很朴素:能离线用、不折腾环境、上手零学习成本、标注文件格式和现有脚本无缝衔接。这几点 1.8.6 全占。界面虽然老,但功能边界很清楚:框选、标签、分类、切换下一张、保存,没有多余干扰。而且汉化打包版把 Python 环境一并免掉,双击就能进界面,这对一台可能连编译器都没有的标注机来说,是实打实的省事。
还有一层是团队协作时的稳定性:多人标同一批数据,如果提前定了 classes.txt 和输出格式,每个人拿到的文件结构完全一致,训练脚本直接就能消费。这个版本源码结构简单,社区里针对它的汉化包、快捷键说明、批量转换脚本非常多,遇到新需求也能快速改,不会卡在黑匣子里。多人协作的场景里,我反而更倾向于用这种老工具,因为它没有账号体系,没有云端同步,每个人的产出就是纯本地文件,好排查也好合并。
3. labelImg 安装与启动:从解压到完成第一张图标注
3.1 解压与目录检查:先确认你拿到的包是完整的
搜过 labelImg 安装教程的人应该都知道,网上教程十有八九在讲配 Python 环境,而这个打包版把这些步骤全略掉了,直接进入使用环节。拿到 zip 先解压,我习惯放到纯英文路径,比如 D:\labelImg-w64,而不是放在带中文用户名的「下载」目录里。虽然打包版对中文路径的容忍度比源码版高,但标注数据路径里有中文,后面接训练脚本时迟早要扫码。解压后先做一次目录检查:
# 在解压后的目录下确认关键文件都在 ls -la # 查看 exe 位宽,PE32+ 表示 x64 file labelImg.exe # 看默认类别文件里预置了哪些类 cat data/predefined_classes.txtfile命令在 Windows 上不一定有,最直观的办法是右键 exe 看属性,或者任务管理器里看架构。data/predefined_classes.txt是 labelImg 启动时预读的类别清单,一行一个类别名,标注时界面里会直接出现这些类,省去每次手输。我建议拿到包先看一眼这个文件,把它替换成自己项目的类别清单。下面是一个典型解压目录的内容:
| 路径 | 作用 |
|---|---|
| labelImg.exe | 主程序,双击启动 |
| data/predefined_classes.txt | 预定义类别清单 |
| locale/ | 翻译文件目录,汉化包常见 |
要注意的是,如果你看到 locale 目录里有 .qm 后缀文件,说明这个汉化版走的是翻译机制;没有的话,就是直接改源码字符串打包的。两种都不影响使用,但后面遇到「汉化不完整」时,判断方法不一样,这个在第 5 章会展开。
3.2 首次启动:VC++ 运行库是唯一可能出问题的地方
双击 labelImg.exe,绝大多数情况直接进界面。但在干净的机器上,可能碰到两种情况。第一种弹窗提示找不到 VCRUNTIME140.dll,这是 PyInstaller 打包程序依赖微软 VC++ 运行库,而精简版系统往往没装。解决方法是装一次微软官方 vc_redist.x64.exe,装完即好,不需要重启。第二种是杀毒软件直接拦截或删除了 exe。PyInstaller 打包程序的特征比较集中,容易被启发式扫描标记,把文件加白名单或从隔离区恢复即可。
这两种情况都不代表软件本身有问题。我自己在一台装了全家桶的机器上遇到过 exe 被隔离的情况,恢复后标注了一整天,没有任何异常。排查闪退有个标准手段:在 cmd 里先 cd 到解压目录,再手动输入 labelImg.exe 回车,双击时被吞掉的报错文本会直接留在终端里,缺哪个 DLL 一眼就能看到。换到正常环境后,这个汉化版的表现非常稳定,可以长时间挂机标图不退出。
3.3 新建标注项目的标准步骤:图片目录、类别文件与保存位置
第一张图之前,按这个顺序准备:建一个 images 目录,把要标注的图放进去;建一个 classes.txt,一行一个类别名;启动 labelImg,用「打开目录」选 images;检查界面右侧当前输出格式是 PascalVOC 还是 YOLO;如果是 YOLO 模式,第一次保存时会让你指定 classes.txt 路径。
一个典型目录结构长这样:
D:\lData\ ├── images\ # 原图 │ ├── 000001.jpg │ └── 000002.jpg ├── classes.txt # 一行一个类别 └── labels\ # 标注文件保存目录给 YOLO 模式指定 classes.txt 这一步很多人会跳过,结果类别编号变成默认的 0、1、2,后面训练脚本一看全对不上。正确做法是先写好 classes.txt,打开目录后立刻设置好。界面里的自动保存开关建议直接打开,并设置默认保存目录,这样切换图像时标注结果会自动落盘。第一次画框按键盘 W 或点右侧画框按钮,拖出一个矩形,松开后输入类别;单张完成按 Ctrl+S;D 切下一张、A 切上一张。这套动作熟练后,一张图平均二十多秒就能出框。
4. 标注数据全链路:从一张图到训练数据文件
4.1 单张图像标注的完整操作链
进入标注界面后,完整的单张流程是:画框,松手,输入类别名或从预定义列表里点选,检查框是否贴边,微调边缘,保存,切下一张。如果提前写了 classes.txt,双击已有框会弹出类别列表,直接点选就行,比每次手输快很多。
微调阶段有个老版本特有的交互细节:拖边界框的四条边和四个角点都能调整,但鼠标必须正正好点在边缘上才生效,否则容易整个框被拖走。新手最容易在这里误操作:本想微调右边,结果整个框平移到旁边。这不算 bug,是这个版本的交互习惯,用几次就适应了。选中框后按 Delete 可以删除误标的框,删除动作会立刻反映在内存里,保存后文件同步更新。
保存动作本身没有玄学,点了保存文件才落盘。如果开了自动保存,切换图像时程序会把前一张的标注先写出。我见过一次比较惨的事故:同事标了三百张图,一直没开自动保存,中途程序崩了,三百张的成果全在内存里蒸发。这种场景没有任何后悔药,只能重标。所以我现在拿到任何标注工具,第一件事永远是找自动保存开关,并且手动保存的习惯也不能丢,两者互为兜底。
4.2 XML 与 TXT:标注产物的字段逐项对照
PascalVOC 的标注产物长这样:
<annotation> <folder>images</folder> <filename>000001.jpg</filename> <source><database>Unknown</database></source> <size> <width>800</width> <height>600</height> <depth>3</depth> </size> <object> <name>cat</name> <bndbox> <xmin>120</xmin> <ymin>100</ymin> <xmax>300</xmax> <ymax>280</ymax> </bndbox> </object> </annotation>size三个字段是标注时刻图像的真实宽高和通道数,训练脚本常拿它来反算归一化坐标;object可以有多个,每标一个目标就多一个 object 块;bndbox都是像素坐标,顺序是左上角和右下角。我见过有人把 ymin 和 ymax 写反,肉眼很难发现但训练效果会明显变差,所以校验脚本里必查 xmin 小于 xmax 且 ymin 小于 ymax。YOLO 格式的产物就简单得多,每行五个数字,空格分隔:
0 0.2625 0.3167 0.2250 0.3000第一个数字是类别编号,对应 classes.txt 里的行序号,从 0 开始;后面四位是归一化后的 cx、cy、w、h。比如 cx=0.2625,含义是框中心在图像宽度的 26.25% 处,不是像素坐标。这个版本保存 YOLO 文件时浮点数位数固定,不用手动补精度,float32 够用,补多了只是让文件变大。
4.3 效率设置与批量转换:三个开关能省一半时间
标注效率不靠手速,靠设置。第一个开关是预定义类别:classes.txt 写全类别后,标注时从列表点选,比手输快得多,也杜绝了拼写不一致。第二个是自动保存加默认保存目录:保存目录固定后,XML 或 TXT 和图片分开放,后续打包数据集时只需拷两个目录。第三个是显示模式:界面里可以隐藏标注框、隐藏标签文字,需要审核时再打开,避免一堆框叠在一起看不清。
如果前期用 PascalVOC 标了一批,后面要切 YOLO,不需要重新标。labelImg 自带转换按钮,但数据量大时直接跑脚本批量处理更快,也更好排查:
import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, class_names): tree = ET.parse(xml_path) root = tree.getroot() w = int(root.find("size/width").text) h = int(root.find("size/height").text) lines = [] for obj in root.iter("object"): name = obj.find("name").text if name not in class_names: continue # 不在类别清单里的直接跳过 cls_id = class_names.index(name) box = obj.find("bndbox") xmin = float(box.find("xmin").text) ymin = float(box.find("ymin").text) xmax = float(box.find("xmax").text) ymax = float(box.find("ymax").text) dw, dh = 1.0 / w, 1.0 / h cx = (xmin + xmax) / 2.0 * dw cy = (ymin + ymax) / 2.0 * dh bw = (xmax - xmin) * dw bh = (ymax - ymin) * dh lines.append(f"{cls_id} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}") return "\n".join(lines)函数输入是单个 XML 路径和类别名列表,返回 YOLO 格式文本。核心逻辑是先按 XML 里记录的图像宽高算出归一化系数 dw、dh,再把像素框换算成中心点和宽高的 0 到 1 小数。使用前确认 XML 里的 width、height 与真实图像一致,否则坐标全偏。批量跑几百个 XML 也就是几秒的事,跑完随机抽几张验证一下,就能交付。
5. 避坑手册:labelImg 使用中最常见的五个翻车现场
这一个章节写的全是我自己踩过或替同事擦过屁股的坑。每一条都是真实发生过的现象,按现象、原因、解决的顺序写,方便你对照排查。
5.1 双击 exe 没反应或闪退
现象:双击后鼠标转两圈,窗口没出现,或者一闪就消失。 原因:最常见是缺 VC++ 运行库,报错弹窗一闪而过,用户只看到闪退。其次是杀毒软件把 exe 隔离了,双击的其实是个空壳。 解决:先在 cmd 里 cd 到解压目录手动运行 labelImg.exe,把真正报错文本露出来。提示缺 DLL 就去装微软官方 vc_redist.x64.exe;提示找不到文件或者干脆没报错,就去杀毒软件隔离区找 exe,恢复并加白名单。最后确认你解压出来的真是 x64 版本,不要在 32 位系统上硬跑。
5.2 打开大图后界面卡到无法画框
现象:打开一张十几 MB 的航拍图或长截图,画框时鼠标明显延迟,拖不动。 原因:老版本用 Qt 组件加载整张原图,超大图缩放时内存和 CPU 开销很大,没有异步加载优化。 解决:标注前先把图像预处理到合理尺寸。常见做法是统一把最长边缩到 2000 像素左右,既保留框选精度,又让界面跟手。同时检查内存占用,不要同时挂着浏览器、IDE 和标注工具抢资源。还有一个容易被忽略的点:如果图片目录里有损坏的图片,打开时会卡住甚至崩,我一般会先跑一遍脚本统计图像是否都能正常读取。
5.3 YOLO 模式下类别编号错乱的玄学
现象:标注没问题,TXT 也生成了,但训练时发现类别 A 和类别 B 对调了,或者出现一个从没标过的类别编号。 原因:YOLO 模式靠 classes.txt 解释编号。如果你中途换过 classes.txt,或者标注时用的类别清单和训练时不一致,编号就漂移。举一个具体例子:classes.txt 里是 dog、cat、person,标了五十张图 dog 都是 0;后来同事在文件开头插了一行 bird,全部旧标注的 dog 从 0 变成 1,模型就全乱了。 解决:classes.txt 一旦定稿,整个标注周期不修改、不排序、不删行。真需要改类别清单,先备份旧文件,改完重新检查所有已标注 TXT 的编号是否还能对上。我自己的习惯是标注前记录 classes.txt 的行号和类名对应表,标注完成后对照一遍再进训练。
5.4 汉化不完整,菜单一半中文一半英文
现象:主菜单是中文的,但某些右键菜单、属性对话框里还是英文。 原因:这个打包版改的是源码字符串,主界面覆盖全,但程序里一些硬编码的英文提示没有进翻译范围。这在社区汉化版里非常常见,不是文件损坏,也不影响数据产出。 解决:如果不介意界面,直接继续用。真在意,可以看解压目录里有没有 locale 文件夹和 .qm 文件:有的话,可以用 Qt Linguist 打开 .ts 补全翻译再重新编译;没有的话,说明是改源码打包的,得改源码重打包,工作量不小,性价比很低。我一般选择忽略,标注工具的核心任务是出数据,不是界面美观。
5.5 标了一下午,退出后发现数据没进文件
现象:切了很多张图,关掉程序,回去看 labels 目录,只有零星几个 XML 或 TXT。 原因:自动保存没开,而且你切换图片的频率比保存快。程序只在保存动作发生时写盘,切换图片不会自动保存,除非开了自动保存开关。 解决:打开界面里的自动保存开关,同时养成 Ctrl+S 的手动习惯。已经发生的话,还有补救办法:重新打开目录,确认自动保存已开启,然后逐张切换图片,切换时会触发保存,把内存里的标注重新写盘。这个坑我踩了不止一次,现在无论用什么标注工具,第一步永远是确认自动保存状态。
6. 标注质量验证:三个不花钱的检查技巧
6.1 脚本校验:先跑一遍,别信眼睛
标注完成后,我习惯在目录里跑一段十几行的校验脚本:检查每个 XML 能不能被解析,坐标有没有越界,TXT 的类别编号有没有超出 classes.txt 范围。健康数据是训练的前提,脚本比人眼靠谱。
import glob import os from xml.etree import ElementTree as ET xmls = glob.glob("labels/*.xml") for f in xmls: root = ET.parse(f).getroot() w = int(root.find("size/width").text) h = int(root.find("size/height").text) for obj in root.iter("object"): xmin, ymin = float(obj.find("bndbox/xmin").text), float(obj.find("bndbox/ymin").text) xmax, ymax = float(obj.find("bndbox/xmax").text), float(obj.find("bndbox/ymax").text) if not (0 <= xmin < xmax <= w and 0 <= ymin < ymax <= h): print(f"[越界] {os.path.basename(f)} {xmin},{ymin},{xmax},{ymax}")这段脚本遍历 labels 目录下所有 XML,先用 size 里的宽高做范围判断。if not 那一行是单条校验,任一边不满足就会打印文件路径和坐标,方便回到 labelImg 里定位修正。跑完没有输出,说明这批 XML 数值上基本健康。
6.2 可视化验证:把框画回原图
脚本只能查数值问题,查不出框偏了半个身位这种质量问题。我习惯在训练前随机抽几十张图,按 XML 坐标把框画回原图,肉眼过一遍。用 PIL 加载原图,遍历 XML 画矩形,保存成带框预览图就行。抽检数量不用多,三五十张足够发现系统性偏移。如果发现某些图框整体向左偏一截,通常不是标错了,而是图像在预处理环节被压缩过,回溯预处理逻辑比一张张改快得多。
6.3 训练前的最后一分钟检查
把标注文件交给训练脚本前,我固定做三件事:核对 images 目录和 labels 目录的文件名一一对应;确认 classes.txt 的类名顺序和训练配置里的类别映射一致;随手打开一个 TXT 看序号有没有超出类别总数。这三步加起来不到一分钟,能挡掉大部分低级事故。有一次批量标注完三千张图,跑训练时发现 mAP 全乱,查了两天,原因就是 classes.txt 被某次操作追加了一行,历史编号整体后移。从那以后,我每次标注交付前都强制走一遍这套校验:先跑数值脚本,再抽预览图,最后对一遍类别映射,三个都过了才敢进训练管线。手头这个汉化打包版拿过去就能用,但用之前记得先把第 3.3 节的目录和类别文件准备好,再按这套习惯走一遍,希望帮到你。
本文还有配套的精品资源,点击获取