我写了一个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()
答案 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)
...