Mentions légales du service

Skip to content
Snippets Groups Projects
soma_validation.py 3.08 KiB
Newer Older
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