Tkinter:图像循环变慢

时间:2018-07-18 14:07:45

标签: python tkinter

我写了一个Tkinter GUI,它应该通过遍历每个3D图像的2D切片来显示3D图像。我阅读了有关如何实现这种图像循环的建议,并建议将after()函数与递归一起使用。原则上,这是我的实现方式:

def load_image(self):
    self.stack = read_3D_image(path)
    slice = self.stack[self.slice_no]
    im = Image.fromarray(slice)
    self.photo = ImageTk.PhotoImage(image=im)
    self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)
    if self.forward is True:
        self.slice_no += 1
        if self.slice_no == 21:
            self.forward = False
    if self.forward is False:
        self.slice_no -= 1
        if self.slice_no == 0:
            self.forward = True
    root.after(10, self.load_image)

这在一段时间内效果很好,但是几分钟后,循环明显变慢了。我猜这是因为迭代次数很高。有办法解决这个问题吗?

编辑:我注意到了这一点:当程序运行时,图像循环将在大约10分钟后减慢到原始频率的一半。当我运行第二个实例时,其循环运行同样缓慢。然后,当我关闭第一个实例时,第二个实例循环立即运行得更快。我是从Eclipse启动的。

更新了完整代码

import glob
import os.path
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np

import helpers


class App():

    def __init__(self, master):
        super().__init__()
        self.frame = tk.Frame(master)
        master.bind("<KP_1>", lambda e: self.is_cell())
        master.bind("<KP_2>", lambda e: self.is_not_cell())
        self.frame.pack()

        self.goto_button = tk.Button(
            self.frame, text="Go to:", command=self.goto)
        self.goto_button.pack(side=tk.TOP)

        self.goto_entry = tk.Entry(self.frame, width=5)
        self.goto_entry.pack(side=tk.TOP)

        self.img_side_length = 100

        self.canvas = tk.Canvas(
            master=self.frame, width=self.img_side_length, height=self.img_side_length)
        self.canvas.pack()

        self.img_label = tk.Label(self.frame, text="Bla")
        self.img_label.pack(side=tk.TOP)

        self.no_cell_button = tk.Button(
            self.frame, text="2: Not cell!", command=self.is_not_cell)
        self.no_cell_button.pack(side=tk.RIGHT)

        self.cell_button = tk.Button(
            self.frame, text="1: Cell!", command=self.is_cell)
        self.cell_button.pack(side=tk.RIGHT)



        self.img_path = "/storage/images/"
        self.img_list = glob.glob(os.path.join(self.img_path, "*"))
        self.img_list.sort()
        self.slice_no = 0
        self.img_no = 0
        self.forward = True
        self.no_of_imgs = len(self.img_list)
        self.stack = []
        self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW)
        self.stack = helpers.read_image_sequence(self.img_list[self.img_no])

        self.classifications = np.zeros(self.no_of_imgs)

        self.out_path = "/dev/null"

        self.loop_image()

    def loop_image(self):

        data = self.stack[self.slice_no]
        im = Image.fromarray(data)
        im = im.resize((self.img_side_length, self.img_side_length))
        self.photo = ImageTk.PhotoImage(image=im)
        self.canvas.itemconfigure(self.image_id, image=self.photo)
        if self.forward is True:
            self.slice_no += 1
            if self.slice_no == 21:
                self.forward = False
        if self.forward is False:
            self.slice_no -= 1
            if self.slice_no == 0:
                self.forward = True
        root.after(10, self.loop_image)

    def next_image(self):
        self.img_no += 1
        self.stack = helpers.read_image_sequence(self.img_list[self.img_no])
        self.img_label['text'] = self.img_list[self.img_no].split("/")[-1]

    def previous_image(self):
        self.img_no -= 1
        self.stack = helpers.read_image_sequence(self.img_list[self.img_no])
        self.img_label['text'] = self.img_list[self.img_no].split("/")[-1]

    def is_cell(self):
        self.classifications[self.img_no] = 1
        with open(self.out_path, "a") as f:
            f.write(str(self.img_no) + "," + str(1) + "\n")
        print(self.classifications)
        self.next_image()

    def is_not_cell(self):
        self.classifications[self.img_no] = 2
        with open(self.out_path, "a") as f:
            f.write(str(self.img_no) + "," + str(2) + "\n")
        print(self.classifications)
        self.next_image()


    def goto(self):
        self.img_no = int(self.goto_entry.get())


root = tk.Tk()

app = App(root)

root.mainloop()

1 个答案:

答案 0 :(得分:3)

您正在每秒创建100张图像,并将它们堆叠在一起。 10分钟后,即有60,000张图像彼此堆叠。当画布上有成千上万个项目时,即使有一个看不见,也存在性能问题。

无需在画布上创建越来越多的图像,只需修改现有图像:

def __init__(self):
    ...
    self.canvas = tk.Canvas(...)
    ...
    # create the image object which will display the image
    self.image_id = self.canvas.create_image(0, 0, anchor=tk.NW)

def load_image(self):
    ...
    self.photo = ImageTk.PhotoImage(image=im)

    # reconfigure the canvas item to show the new image
    canvas.itemconfigure(self.image_id, image=self.photo)
    ...