调用模型冻结并在 exe 中打开新窗口。 ultralytics+tkinter+pyinstaller

问题描述 投票:0回答:1

我遇到一个问题,Tkinter 应用程序在转换为 exe 时,每次加载 YOLO 模型时都会冻结并打开一个新窗口。我原来的程序非常广泛,所以我重新创建了一个来演示该问题:

from io import StringIO
memory_buffer = StringIO()
sys.stdout = memory_buffer
import tkinter as tk
from ultralytics import YOLO
import cv2 as cv
global testimg
testimg = cv.imread("testimg.jpg")

class MyGUI:
    def __init__(self):
        self.root = tk.Tk() # root here is window name now
        self.root.geometry("600x400")
        self.root.columnconfigure(0, weight = 1)
        self.root.rowconfigure(0, weight = 1)
        self.root.rowconfigure(1, weight = 1)
        self.root.rowconfigure(2, weight = 1)
        self.buttonmodel1 = tk.Button(self.root, text = "Model 1", bg = "#c9c9c9", bd= 5, width = 200, command = self.button1pressed)
        self.buttonmodel1.grid(row =0, column=0, sticky= "WENS", padx = 3)
        self.buttonmodel2 = tk.Button(self.root, text = "Model 2", bg = "#c9c9c9", bd= 5, width = 200)
        self.buttonmodel2.grid(row =1, column=0, sticky= "WENS", padx = 3)
        self.buttonmodel3 = tk.Button(self.root, text = "Model 3", bg = "#c9c9c9", bd= 5, width = 200)
        self.buttonmodel3.grid(row =2, column=0, sticky= "WENS", padx = 3)
        self.root.mainloop() 
        
    def button1pressed(self):
        global testimg
        model1 = YOLO("model1.pt")
        model2 = YOLO("model2.pt")
        model3 = YOLO("model3.pt")
        resultsmodel1 = model1.predict(testimg)
        print("model1")
        resultsmodel2 = model2.predict(testimg)
        print("model2")
        resultsmodel3 = model3.predict(testimg)
        print("model3")
MyGUI()

转换为exe使用:

pyinstaller --collect-data ultralytics Model_Test.py --onefile --windowed

from io import StringIO
memory_buffer = StringIO()
sys.stdout = memory_buffer

用于缓解使用 ultralytics + pyinstaller 的已知问题:

https://github.com/ultralytics/ultralytics/issues/7064

使用 Ultralytics 将 Python 转换为 EXE 文件时出现问题

在 VS 2022 中调试时不存在此类问题,只有当程序打包并作为 exe 运行时才会出现此类问题。所有模型文件与exe位于同一目录中。

看起来,一旦调用

.predict()
,主窗口就会冻结,控制台会立即弹出,并出现一个新的相同窗口。如果关闭,程序将按预期恢复,不会出现其他错误:

original window left, with new window created shortly after button is pressed

似乎是一个非常小众的问题,我猜想 Ultralytics + Pyinstaller + Tkinter 出了问题。

如果需要更多信息,请提供建议或让我知道。

python tkinter pyinstaller yolov8
1个回答
0
投票

看起来您遇到了一个问题,并且 tkinter 循环之间的复杂交互有解决方案:

  1. 线程:预测冻结的最佳方法,它可以防止这种情况发生
  2. 标准输出处理:确保标准输出重定向不会干扰 GUI
  3. PyInstaller 配置:确保 exe 文件中包含所有依赖项

这是代码解决方案:

import tkinter as tk
from ultralytics import YOLO
import cv2 as cv
import threading
import sys
from io import StringIO

memory_buffer = StringIO() # Output Handling
sys.stdout = memory_buffer

global testimg
testimg = cv.imread("testimg.jpg")

class MyGUI:
    def __init__(self):
        self.root = tk.Tk()
        self.root.geometry("600x400")
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        self.root.rowconfigure(1, weight=1)
        self.root.rowconfigure(2, weight=1)
        self.buttonmodel1 = tk.Button(self.root, text="Model 1", bg="#c9c9c9", bd=5, width=200, command=self.button1pressed)
        self.buttonmodel1.grid(row=0, column=0, sticky="WENS", padx=3)
        self.buttonmodel2 = tk.Button(self.root, text="Model 2", bg="#c9c9c9", bd=5, width=200)
        self.buttonmodel2.grid(row=1, column=0, sticky="WENS", padx=3)
        self.buttonmodel3 = tk.Button(self.root, text="Model 3", bg="#c9c9c9", bd=5, width=200)
        self.buttonmodel3.grid(row=2, column=0, sticky="WENS", padx=3)
        self.root.mainloop()

    def button1pressed(self):
        threading.Thread(target=self.run_models).start() # Threading solution

    def run_models(self):
        global testimg
        model1 = YOLO("model1.pt")
        model2 = YOLO("model2.pt")
        model3 = YOLO("model3.pt")
        resultsmodel1 = model1.predict(testimg)
        print("model1")
        resultsmodel2 = model2.predict(testimg)
        print("model2")
        resultsmodel3 = model3.predict(testimg)
        print("model3")

MyGUI()

PyInstaller Script 4 与你的相同

如果问题仍然存在,请执行以下操作:

  1. 检查输出:检查任何错误是否缺少依赖项或类似的内容
  2. 不使用
    --windowed
    运行:如果问题仍然存在,请查看控制台进行调试
  3. DEpendency :确保所有 YOLO 依赖项与 exe 文件位于同一目录中
© www.soinside.com 2019 - 2024. All rights reserved.