I'm using CustomTkinter to build a GUI for medical image segmentation. I have a button to load the images, and I’ve previously saved my trained model as "unet_model.h5". I want to display the predicted segmentation masks in the interface so that doctors can visualize the segmentations, but they currently don’t appear. Instead, I get the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\maria\anaconda3\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "C:\Users\maria\anaconda3\Lib\site-packages\customtkinter\windows\widgets\ctk_button.py", line 554, in _clicked
self._command()
File "C:\Users\maria\AppData\Local\Temp\ipykernel_27908\467682517.py", line 141, in loadimg
segment_volume(pasta)
File "C:\Users\maria\AppData\Local\Temp\ipykernel_27908\467682517.py", line 131, in segment_volume
show_slice(current_slice)
File "C:\Users\maria\AppData\Local\Temp\ipykernel_27908\467682517.py", line 93, in show_slice
img_label.configure(image=img_label._image_ref)
File "C:\Users\maria\anaconda3\Lib\site-packages\customtkinter\windows\widgets\ctk_label.py", line 222, in configure
self._update_image()
File "C:\Users\maria\anaconda3\Lib\site-packages\customtkinter\windows\widgets\ctk_label.py", line 144, in _update_image
self._label.configure(image=self._image)
File "C:\Users\maria\anaconda3\Lib\tkinter\__init__.py", line 1702, in configure
return self._configure('configure', cnf, kw)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\maria\anaconda3\Lib\tkinter\__init__.py", line 1692, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage7" doesn't exist
This is the code I tried:
import os
import cv2
import numpy as np
from tensorflow.keras.models import load_model
import customtkinter
from tkinter import filedialog
from PIL import Image, ImageTk
#Pre-processing before segmentation
def natural_key(string_):
import re
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]
def resize_and_pad(img, size):
desired_size = size[0]
old_size = img.shape[:2]
if old_size[0] == 0 or old_size[1] == 0:
print("Warning: Image with zero dimensions. Skip")
return None
ratio = float(desired_size) / max(old_size)
new_size = tuple([int(x*ratio) for x in old_size])
if new_size[0] == 0 or new_size[1] == 0:
print("Warning: Redimensioning with zero dimensions. Skip")
return None
img_resized = cv2.resize(img, (new_size[1], new_size[0]))
delta_w = desired_size - new_size[1]
delta_h = desired_size - new_size[0]
top, bottom = delta_h//2, delta_h-(delta_h//2)
left, right = delta_w//2, delta_w-(delta_w//2)
color = [0, 0, 0]
new_img = cv2.copyMakeBorder(img_resized, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
return new_img
def load_test_volume(test_folder, img_size=(256, 256), downsample_factor=1):
slice_folder = os.path.join(test_folder)
slice_files = sorted(
[f for f in os.listdir(slice_folder) if f.endswith(('.tif', '.png'))],
key=natural_key
)
slices = []
for slice_file in slice_files:
slice_path = os.path.join(slice_folder, slice_file)
img = cv2.imread(slice_path, cv2.IMREAD_GRAYSCALE)
if img is None:
print(f"Warning: impossible to read the image {slice_path}. Skip")
continue
img = cv2.resize(img, (0, 0), fx=downsample_factor, fy=downsample_factor, interpolation=cv2.INTER_LINEAR)
img = resize_and_pad(img, img_size)
if img is None:
continue
slices.append(img)
return slices
#Load model
MODEL_PATH = "unet_model.h5"
model = load_model(MODEL_PATH, compile=False)
current_slice = 0
Xtest_global = None
preds_global = None
img_label = None
mask_label = None
def show_slice(index):
global img_label, mask_label
if Xtest_global is None or preds_global is None:
return
img = (Xtest_global[index].squeeze() * 255).astype(np.uint8)
img_pil = Image.fromarray(img)
img_tk = ImageTk.PhotoImage(img_pil)
img_label._image_ref = img_tk
img_label.configure(image=img_label._image_ref)
mask = (preds_global[index].squeeze() * 255).astype(np.uint8)
mask_pil = Image.fromarray(mask)
mask_tk = ImageTk.PhotoImage(mask_pil)
mask_label._image_ref = mask_tk
mask_label.configure(image=mask_label._image_ref)
def next_slice():
global current_slice
if Xtest_global is None:
return
if current_slice < len(Xtest_global)-1:
current_slice += 1
show_slice(current_slice)
def prev_slice():
global current_slice
if Xtest_global is None:
return
if current_slice > 0:
current_slice -= 1
show_slice(current_slice)
#Segmentation
def segment_volume(folder_path):
global Xtest_global, preds_global, current_slice
slice_imgs = load_test_volume(folder_path, downsample_factor=1)
if len(slice_imgs) == 0:
print("None valid image found in the folder")
return
X_slices = [img[..., np.newaxis] / 255.0 for img in slice_imgs]
Xtest_global = np.array(X_slices)
preds_global = (model.predict(Xtest_global) > 0.5).astype("int32")
current_slice = 0
show_slice(current_slice)
prev_btn.configure(state="normal")
next_btn.configure(state="normal")
#Load images
def loadimg():
pasta = filedialog.askdirectory()
if pasta:
print("Selected folder", pasta)
segment_volume(pasta)
customtkinter.set_appearance_mode("light")
customtkinter.set_default_color_theme("dark-blue")
root = customtkinter.CTk()
root.geometry("900x600")
frame_top = customtkinter.CTkFrame(master=root)
frame_top.pack(pady=10, padx=10, fill="x")
label = customtkinter.CTkLabel(master=frame_top, text="Segmentator OCT- Retina", font=("Roboto", 24))
label.pack(pady=12)
botao = customtkinter.CTkButton(master=frame_top, text="Load OCT Volume", command=loadimg)
botao.pack(pady=5)
frame_imgs = customtkinter.CTkFrame(master=root)
frame_imgs.pack(pady=10, padx=10, fill="both", expand=True)
img_label = customtkinter.CTkLabel(master=frame_imgs)
img_label.pack(side="left", padx=10, pady=10)
mask_label = customtkinter.CTkLabel(master=frame_imgs)
mask_label.pack(side="right", padx=10, pady=10)
frame_nav = customtkinter.CTkFrame(master=root)
frame_nav.pack(pady=10)
prev_btn = customtkinter.CTkButton(master=frame_nav, text="Anterior", command=prev_slice, state="disabled")
prev_btn.pack(side="left", padx=20)
next_btn = customtkinter.CTkButton(master=frame_nav, text="Próximo", command=next_slice, state="disabled")
next_btn.pack(side="right", padx=20)
root.mainloop()
print()(andprint(type(...)),print(len(...)), etc.) to see which part of code is executed and what you really have in variables. It is called"print debugging"and it helps to see what code is really doing.ImageTk.PhotoImage)CTkLabelprefersCTkImageinstead ofImageTk.PhotoImage