CustomTkinter医学图像分割GUI中U-Net预测分割掩码显示失败及报错解决求助
CustomTkinter医学图像分割GUI中U-Net预测分割掩码显示失败及报错解决求助
我目前正在用CustomTkinter开发一个医学图像分割的可视化GUI,核心需求是:点击加载按钮导入医学图像切片文件夹,用预先训练好并保存为unet_model.h5的U-Net模型生成分割掩码,最后在界面里同时展示原始切片和对应的预测掩码,方便医生查看结果。
但现在遇到了棘手的问题:预测的分割掩码完全显示不出来,还直接抛出了Tkinter的回调错误,完整报错信息如下:
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
我的代码逻辑大致是:点击加载按钮后读取文件夹里的医学切片,用模型预测生成掩码,然后通过show_slice函数把原始图和掩码显示在CustomTkinter的Label组件里。但错误正好触发在show_slice更新Label图像的步骤,下面是我相关的核心代码片段:
模型加载与全局变量定义
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 # 预加载U-Net模型 MODEL_PATH = "unet_model.h5" model = load_model(MODEL_PATH, compile=False) # 全局变量:存储测试切片、预测结果和显示用的Label组件 current_slice = 0 Xtest_global = None preds_global = None img_label = None mask_label = None
错误触发的核心函数:show_slice
def show_slice(index): global img_label, mask_label if Xtest_global is None or preds_global is None: return # 处理原始切片并转换为Tkinter可用的图像格式 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) # 处理预测掩码并转换为Tkinter可用的图像格式 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 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 # 对整个文件夹的切片执行分割预测 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, verbose=1) # 显示第一张切片 current_slice = 0 show_slice(current_slice)
GUI入口回调函数
def loadimg(): pasta = filedialog.askdirectory() if not pasta: return segment_volume(pasta) # 省略CustomTkinter窗口初始化、Label与按钮创建代码 # 大致逻辑:创建窗口,添加img_label/mask_label用于显示图像,加载按钮绑定loadimg函数
我尝试过把ImageTk对象存在Label的_image_ref属性里防止被垃圾回收,但还是出现了image "pyimage7" doesn't exist的错误,完全搞不懂问题出在哪,有没有大佬能帮我排查一下问题根源或者给个解决思路?
内容来源于stack exchange
相关产品推荐
相关产品推荐

