用于切换图像显示的Python函数

时间:2018-01-19 21:17:52

标签: python image tkinter classification visualization

我有一个运行在实时数据上的python 3脚本,它调用分类函数,返回0或1.我想要的是一个窗口根据分类器返回的内容显示图像。

以下是我的分类器脚本的简单版本:

from random import randint
import time

def classifier():
    time.sleep(4)
    return randint(0,1)

while True:
    classification=classifier()

这是我到目前为止为视觉效果提出的脚本:

import tkinter as tk
from PIL import Image,ImageTk

root = tk.Tk()


img1=ImageTk.PhotoImage(Image.open('left.jpg'))
img2=ImageTk.PhotoImage(Image.open('right.jpg'))

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master, bg="")
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.arrow=tk.Label(self, image=img1)
        self.arrow.image=img1 #must keep this otherwise will be discarded
        self.arrow.pack()
        self.pack()


def updateImg(img):
    app.arrow.config(image=img)
    app.arrow.image=img
    app.arrow.pack()


app = Application(master=root)

app.mainloop() 

我的问题是连接两个脚本,以便分类值确定实时显示的图像。从理论上讲,我希望能够从分类器脚本

中调用updateImg

2 个答案:

答案 0 :(得分:0)

当您在GUI代码中使用其他代码,然后在其他代码中使用GUI代码时更容易 - 它被称为“GUI包装器”。

GUI的问题在于它必须运行mainloop,它始终有效(直到关闭窗口)并且您无法运行其他循环。您可以使用thread同时运行其他循环,但tkinter不是线程安全的,并且更改其他thead中的小部件可能会产生问题

您可以使用root.after定期运行一些代码,然后两个循环没有问题,因为mainloop会为您运行它。

import tkinter as tk
from PIL import Image,ImageTk
from random import randint, randrange
import time

# --- classes ---

class Application(tk.Frame):

    def __init__(self, master=None):
        super().__init__(master, bg="")
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        # create empty label
        self.arrow = tk.Label(self)
        self.arrow.pack()

    def update_image(self, img):
        # set image in label
        self.arrow.config(image=img)

        # because image is assigned to global list `imgs`
        # so this command may not be needed        
        self.arrow.image = img

# --- functions ---

def classifier():
    # return randint(0, len(imgs)-1) # with -1
    return randrange(0, len(imgs))   # without -1

def update_loop():
    # run your classifier from other file
    selected = classifier()

    # get image from list
    img = imgs[selected]

    # update image in window
    app.update_image(img)

    # run it again after 4000ms
    root.after(4000, update_loop)

# --- main ---

root = tk.Tk()

# list with images (create after creating `root`)
imgs = [
    ImageTk.PhotoImage(Image.open('left.jpg')),
    ImageTk.PhotoImage(Image.open('right.jpg')),
]    

# creacte app
app = Application(root)

# run it first time
update_loop()

# start "engine"
app.mainloop() 

答案 1 :(得分:0)

这就是我使用它的原因!

import tkinter as tk
from PIL import Image,ImageTk
from threading import Thread
from queue import Queue
import time
from random import randint

q=Queue() #both threads can access the queue

def GUIthread(): #all GUI actions take place in this thread
    root = tk.Tk() 
    img1=ImageTk.PhotoImage(Image.open('left.jpg'))
    img2=ImageTk.PhotoImage(Image.open('right.jpg'))

    def updateImage(classification):
        if classification ==1:
            root.arrow.config(image=img2)
            root.arrow.image=img2
            root.arrow.pack()
        else:
            root.arrow.config(image=img1)
            root.arrow.image=img1
            root.arrow.pack()

    def checkQueue():
        classification=q.get()
        updateImage(classification)
        q.task_done()
        root.after(1000,checkQueue)

    root.arrow=tk.Label(image=img1)
    root.arrow.image=img1
    root.arrow.pack()          
    root.after(1, checkQueue)
    root.mainloop()


def classifier(): #mimics a thread that needs to be run continuously (collecting live data)
    while 1: 
        time.sleep(2)
        q.put(randint(0,1))


t=Thread(target=GUIthread)
t.start()
classifier()