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()

您每秒创建100个图像,并将它们堆叠在一起。10分钟后,就有6万张图像叠加在一起。画布上有数以万计的项目时会出现性能问题,即使只有一个项目是不可见的。

与其在画布上创建越来越多的图像,不如修改现有图像:

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)
...

最新更新