概述
LabelImg 是一款广受欢迎的开源图像标注工具,支持 Pascal VOC、YOLO 等格式,广泛应用于目标检测数据集的制作。在 Windows 系统上,官方推荐使用 PyInstaller 将其打包为独立的 .exe 可执行文件,便于分发和使用。
官方提供的打包命令如下:
python
pyinstaller --hidden-import=pyqt5 --hidden-import=lxml -F -n "labelImg" -c labelImg.py -p ./libs -p ./
然而,直接打包后的 labelImg.exe 无法自动加载我们自定义的预设标签(如 predefined_classes.txt) 。即使将该文件放在 exe 同级目录或 data/ 子目录下,程序仍会因路径解析问题而忽略它,导致每次启动都需手动输入类别,效率低下。
本文将通过修改 LabelImg 启动逻辑 ,使其在打包后能正确识别并加载位于可执行文件同级目录下的 data/predefined_classes.txt,从而实现"开箱即用"的自定义标签体验。
当然,幽络源这里也提供打包后的,方便不带有python环境的标注员使用=>https://pan.quark.cn/s/07235f2bb6fb
主要内容
问题根源:__file__ 在 PyInstaller 打包后失效
LabelImg 原始代码中,默认的类别文件路径是这样设置的:
python
default=os.path.join(os.path.dirname(__file__), "data", "predefined_classes.txt")
如图

在开发环境(.py 脚本运行)时,__file__ 指向 labelImg.py 所在目录,路径正确;
但在 PyInstaller 打包为单文件 EXE 后,__file__ 指向的是 PyInstaller 解压到临时目录(如 _MEIxxxxx)中的内部文件路径,而非用户放置 EXE 的实际目录。
因此,程序会在临时目录中寻找 data/predefined_classes.txt,而不会去 EXE 所在目录查找,导致自定义标签无法加载。
解决方案:动态获取 EXE 所在目录
我们需要替换 os.path.dirname(__file__),新增以下函数来获取真正的可执行文件所在目录:
python
def get_executable_dir():
"""返回可执行文件所在目录(兼容开发环境和 PyInstaller 打包)"""
if getattr(sys, 'frozen', False):
# PyInstaller 打包后
return os.path.dirname(sys.executable)
else:
# 开发环境
return os.path.dirname(os.path.abspath(__file__))
如图

然后在参数解析部分,将默认类别文件路径改为:
python
exec_dir = get_executable_dir()
default_class_file = os.path.join(exec_dir, "data", "predefined_classes.txt")
然后注释掉原来的class_file参数获取方式,将class_file参数设置为获取到的default_class_file
python
argparser.add_argument("class_file", default=default_class_file, nargs="?")
如图

打包与使用步骤
修改后,执行打包命令
bash
pyinstaller --hidden-import=pyqt5 --hidden-import=lxml -F -n "labelImg" -c labelImg.py -p ./libs -p ./
打包完成后将会在dist目录下生成exe文件,然后幽络源这里在exe同级目录下加入了包含在data目录下的预设标签文件,如图

双击打包后的exe文件,如图可以看到自带了我们data目录下predefined_classes.txt所设定的标签

再如下图,使用功能完全正常

结语
通过简单的源码调整,我们成功解决了 LabelImg 打包为 EXE 后无法加载外部预设标签的问题。这一改进极大提升了标注效率,特别适合需要频繁使用固定类别列表的团队或项目。