import tkinter as tknt from typing import Union import numpy as nmpy from PIL import Image as image_t, ImageTk as tk_image_t array_t = nmpy.ndarray class soma_validation_window_t: __slots__ = ( "lmap", "mip", "mip_4_display", "root", "canvas", "tk_image", "canvas_image", ) lmap: array_t mip: array_t mip_4_display: array_t root: tknt.Tk canvas: tknt.Canvas tk_image: tk_image_t canvas_image: int def __init__(self, lmap: array_t, mip_axis: int = -1, color_version: bool = True): """""" mip = nmpy.max(lmap, axis=mip_axis) if color_version: mip_4_display = _ColoredVersion(mip) else: mip_4_display = _ScaledVersion(mip) root = tknt.Tk() canvas = tknt.Canvas(root, width=mip.shape[1], height=mip.shape[0]) tk_image = _TkImageFromNumpyArray(mip_4_display, root) canvas_image = canvas.create_image(0, 0, anchor="nw", image=tk_image) canvas.pack() canvas.bind("<Button-1>", self._DeleteSoma) for field in self.__class__.__slots__: setattr(self, field, eval(field)) def LaunchValidation(self) -> None: """""" self.root.mainloop() # scikit-image.relabel(self.lmap) def _DeleteSoma(self, event: tknt.EventType.ButtonPress) -> None: """""" row = event.y col = event.x value = self.mip[row, col] if value > 0: self.lmap[self.lmap == value] = 0 soma_bmap = self.mip == value self.mip[soma_bmap] = 0 if self.mip_4_display.ndim == 1: self.mip_4_display[soma_bmap] = 0 else: for channel in range(self.mip_4_display.shape[2]): self.mip_4_display[..., channel][soma_bmap] = 0 self.tk_image = _TkImageFromNumpyArray(self.mip_4_display, self.root) self.canvas.itemconfigure(self.canvas_image, image=self.tk_image) def _ScaledVersion(image: array_t, offset: int = 50) -> array_t: """ offset: Value of darkest non-background intensity """ scaling = (255.0 - offset) / nmpy.max(image) output = scaling * image + offset output[image == 0] = 0 return output.astype(nmpy.uint8) def _ColoredVersion(image: array_t) -> array_t: """""" max_label = nmpy.amax(image) labels = tuple(range(1, max_label+1)) half_length = int(round(0.5 * max_label)) shuffled_labels = labels[half_length:] + labels[:half_length] shuffled_image = nmpy.zeros_like(image) for label, shuffled_label in enumerate(shuffled_labels): shuffled_image[image == label] = shuffled_label output = nmpy.dstack((image, shuffled_image, max_label - image)) output = (255.0 / max_label) * output output[image == 0] = 0 return output.astype(nmpy.uint8) def _TkImageFromNumpyArray(array: array_t, parent: Union[tknt.Widget, tknt.Tk]) -> tk_image_t: """""" pil_image = image_t.fromarray(array) output = tk_image_t.PhotoImage(master=parent, image=pil_image) return output