Pyinstaller打包YOLO8项目GUI界面多次出现以及控制台闪烁问题解决方案

项目大致情况

  • 一个利用 YOLO8 进行内容检测的项目,项目中除了通过 YOLO8 实现的内容检测部分,还有通过 PyQt5 实现的 GUI
  • 项目使用 Pyinstaller 进行打包
  • 所使用的环境:
    • Windows 10
    • PyCharm
    • Anaconda
    • Python 3.10
    • Ultralytics 8.1.29
    • PyQt5 5.15.10
    • Pyinstaller 5.13.2

所遇到的问题与解决方案

阶段一:报错找不到模块或资源

初次尝试使用 Pyinstaller 进行打包:

pyinstaler -w main.py

此处 main.py 是进行打包的文件名,尝试运行打包出来的 exe,报错找不到文件之类的,解决办法:

  1. 模块未被打包: 由于 Ultralytics 包比较新,Pyinstaller 还没有包含自动将这个模块打包进去的指令,所以需要到你的这个虚拟环境目录下找到 Ultralytics 文件夹,将其复制到你的 python 项目目录下,然后使用 pyinstaller 打包指令时添加上额外的数据打包指令,即使用:
    pyinstaller --collect-data ultralytics -w main.py
    
    进行打包
  2. 额外资源未被打包: 由于使用了自己的 .bt 文件模型以及其他许多图片资源素材,这些内容也需要被打包进去,不然 exe 运行时找不到这些内容就会报错,因此可以在打包时先使用:
    pyi-makespec --collect-data ultralytics -w main.py
    
    生成 .spec 文件,在这个文件中的
    # -*- mode: python ; coding: utf-8 -*-
    from PyInstaller.utils.hooks import collect_data_files
    
    datas = [('res', '.')]
    datas += collect_data_files('ultralytics')
    
    第一个 datas 这里进行修改,默认生成的是 datas = [] , 你需要在里面添加上你的资源所在的文件夹,便于打包,例如我在项目目录下添加了 res 这个文件夹,并且把所有的资源都放进去,所以最终就是 datas = [('res', '.')],这样你的这些额外资源就也会被打包进行,理论上你的 exe 就能正常工作了,但是!总是会有意外发生!这就是阶段二的内容了

阶段二:exe 运行奇怪报错

正常来说,你把所有这些 python 模块和资源文件都打包好了,就能正常运行了,但是这边由于用了 -w 这个不显示控制台的打包方法,如果你的程序代码里包含了 print() 或者 LOGGER 之类的打印信息,那么这里就会由于找不到控制台报一些奇怪的错误

如果是 print() 这个很好处理,你自己写的都注释掉就行,但是这边用了 UltralyticsYOLO 模块,它 __init__LOGGER 这个东西,在好几个文件里都有涉及,用来输出一些 YOLO 的过程信息,所以你需要找到 Ultralytics 文件夹里 utils 文件夹下的 __init__.py 在大概 270 行左右:

# Set logger
# LOGGER = set_logging(LOGGING_NAME, verbose=VERBOSE)  # define globally (used in train.py, val.py, predict.py, etc.)
LOGGER = None

LOGGER 设为 None,这样之后就不会输出东西了,然后也要找到调用了 LOGGER 的几个文件,基本上是 Ultralytics 文件夹里 engine 文件夹下的几个文件,可以搜索一下然后把所有 LOGGER 都注释了,如果在单行的条件语句里记得补充上 pass 不然会报错

这样把所有的涉及输出到控制台的东西都处理好了,再次重新打包,你的 exe 应该就可以正确运行了,但是!还是会有问题,不然就不会有这篇记录了!

阶段三:启动涉及 YOLO预测功能时,控制台会闪烁出现,同时生成了额外的GUI界面

这部分问题是最摸不着头脑的,想到了估计会是多线程的问题,但是不知道具体问题在哪里。最后在 Ultralytics 以及 PyinstallerGitHub 问题讨论区留下问题,得到了大佬的解答才得以解决:

  1. 添加控制多线程的内容: 需要在主程序运行自己的 PyQt 界面的代码执行前,先添加额外的一个:

    if __name__ == '__main__':
    	import multiprocessing
    	multiprocessing.freeze_support()
    	
    	app = QApplication(sys.argv)
    	window = Window()
    	window.show()
    	sys.exit(app.exec_())
    

    应该是通过 multiprocessing.freeze_support() 避免多线程的一些问题,这样就能避免生成额外的 GUI 界面

  2. 修改YOLO中存在线程问题的代码: 找到 Ultralytics 文件夹里 utils 文件夹下的 torch_utils.py 文件,里面的 73 行左右,这边在获取机器的 cpu 信息的时候应该是有启动了多线程之类的东西:

    def get_cpu_info():
    	# """Return a string with system CPU information, i.e. 'Apple M2'."""
    	# import cpuinfo  # pip install py-cpuinfo
    	#
    	# k = "brand_raw", "hardware_raw", "arch_string_raw"  # info keys sorted by preference (not all keys always available)
    	# info = cpuinfo.get_cpu_info()  # info dict
    	# string = info.get(k[0] if k[0] in info else k[1] if k[1] in info else k[2], "unknown")
    	import wmi
    
    	c = wmi.WMI()
     	string = c.Win32_Processor()[0].Name
    	return string.replace("(R)", "").replace("CPU ", "").replace("@ ", "")
    

    问题应该出在 cpuinfo 这个模块估计会启动其他线程造成一些冲突之类,导致了这个控制台在启动 YOLO 的检测时会突然出现闪烁的问题,所以我修改成通过 wmi 模块简单拿到 cpu 型号信息这样一个简单方法去规避了问题。

    如果你是按我这样在修改完 73 行附近这个函数,那应该基本所有问题就都解决了,如果你这边的 cpu 信息获取方法调整的和我不一样,注意 164 行左右的调用也需要调整,或者你也可以直接在那边写死 cpu 信息,不过这样程序运行平台就很局限了

总结

把以上三个阶段的内容都修改完,你的 YOLO 以及 PyQt5 项目应该就能被 Pyinstaller 完美打包好,并且正常的运行了!如果你还希望修改一下 exe 的 icon,记得先在 pyqt 的窗口类里面加上 icon的信息,同时在打包的时候指定上 icon文件:

from PyQt5.QtGui import QIcon

self.setWindowIcon(QIcon('res/your_icon.ico'))
pyi-makespec --collect-data ultralytics -F -w -i your.ico main.py
pyinstaller main.spec

这样最终可以打包出来一个单独的 exe 文件,并且是你的icon,最后附上一个 pngico 文件的代码:

from PIL import Image


def make_icon():
    # 读取PNG图像
    png_image = Image.open('icon.png')

    # 定义要生成的ICO文件中的各个尺寸
    sizes = [(16, 16), (32, 32), (48, 48), (64, 64), (256, 256)]

    # 创建ICO文件
    ico_image = Image.new('RGBA', (max(sizes)), (255, 255, 255, 0))

    # 将PNG图像按照不同尺寸复制到ICO文件中
    for size in sizes:
        resized_image = png_image.resize(size, Image.ANTIALIAS)
        ico_image.paste(resized_image, (0, 0))

    # 保存ICO文件
    ico_image.save('output.ico')


if __name__ == '__main__':
    make_icon()

写在最后

第一次做 YOLO 以及 PyQt5 并且最后用 Pyinstaller 来打包,遇到这些找了很多内容,最后在 GitHub 大佬帮助下终于完美解决,记录一下,希望能帮助到同样遇到类似问题的朋友!

打包yolo项目使用pyinstaller,你可以按照以下步骤操作: 1. 在控制台中输入命令 "pyinstaller 文件名.py",例如:"pyinstaller App.py"。这将会使用pyinstaller打包你的项目。 2. 如果你希望打开程序时不出现命令行窗口,可以在打包命令中添加参数"-w",例如:"pyinstaller -w App.py"。但是在第一次打包时,建议不要加"-w"参数,这样你可以看到报错信息。 3. 在切换盘符时,输入命令"E:"即可切换到E盘。如果需要进入某一文件夹,使用命令"cd 文件夹名",例如:"cd yolo_project"。这些操作在命令行下都是相同的。 4. 在项目所在目录下打开命令行窗口,并输入命令"python 文件名.py"来测试运行程序。如果没有报错,说明已经成功进行了一部分。 5. 在打包结束后,需要注意将yolo.py文件中的model_path、anchors_path和classs_path这三个文件的目录设置为相对路径。然后,在打包生成的.exe文件所在目录下创建一个model_path文件夹,并将这三个.h5和.txt文件拷贝进去。因为pyinstaller无法自动将这些文件打包进去。如果不注意这一点,在开发机器上可以正常运行,但在其他电脑上可能会出错。 6. 最后,你可以在pyinstaller生成的文件夹中找到打包后的可执行文件,例如"App(tiny)"文件夹。在该文件夹下,你可以创建一个"model_data"文件夹,并将运行yolo所使用的权重文件等都拷贝进去。这样,你的打包项目就可以正常运行了。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [使用pyinstaller打包YOLO3拷贝到别的电脑无法运行](https://blog.csdn.net/weixin_43062898/article/details/114546009)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值