Source code for simba.roi_tools.roi_selector_circle_tkinter

__author__ = "Simon Nilsson; sronilsson@gmail.com"

from tkinter import *
from typing import Tuple

import cv2
import numpy as np
from PIL import Image, ImageTk

from simba.roi_tools.roi_utils import get_image_from_label
from simba.utils.checks import (check_if_valid_rgb_tuple, check_instance,
                                check_int)
from simba.utils.warnings import ROIWarning

DRAW_FRAME_NAME = "DEFINE SHAPE"


[docs]class ROISelectorCircle(object): """ A class to allow users to interactively select a Region of Interest (ROI) circle from an image displayed in a Tkinter window. .. video:: tutorials_rst/img/roi/draw_circle.webm :width: 900 :loop: :muted: :align: center .. seealso:: For OpenCV based method, see :func:`simba.video_processors.roi_selector_circle.ROISelectorCircle` :param Toplevel img_window: The Tkinter Toplevel window containing the image. :param int thickness: The thickness of the ROI selection circle. :param Tuple[int, int, int] clr: The color of the ROI circle rectangle in RGB format. :example: """ def __init__(self, img_window: Toplevel, thickness: int = 10, clr: Tuple[int, int, int] = (147, 20, 255)): check_instance(source=self.__class__.__name__, instance=img_window, accepted_types=(Toplevel,)) check_int(name=f'{self.__class__.__name__} thickness', value=thickness, min_value=1) check_if_valid_rgb_tuple(data=clr) self.thickness, self.clr, self.img_window = thickness, clr, img_window self.img_lbl = img_window.nametowidget("img_lbl") self.img = get_image_from_label(self.img_lbl) self.img_cpy = self.img.copy() self.w, self.h = self.img.shape[1], self.img.shape[0] self.drawing, self.clr, self.thickness = False, clr, thickness self.circle_center, self.circle_radius = (-1, -1), 1 self.img_window.bind("<Button-1>", self.mouse_start) self.img_window.bind("<B1-Motion>", self.mouse_move) self.img_window.bind("<ButtonRelease-1>", self.mouse_release) def mouse_start(self, event): self.drawing = True self.circle_center = (event.x, event.y) self.circle_radius = 0 def mouse_move(self, event): if self.drawing: self.circle_radius = int(np.sqrt((event.x - self.circle_center[0]) ** 2 + (event.y - self.circle_center[1]) ** 2)) self.update_image() def mouse_release(self, event): self.drawing = False self.update_image() def update_image(self): self.img_cpy = self.img.copy() self.img_cpy = cv2.circle(self.img_cpy, self.circle_center, self.circle_radius, self.clr, self.thickness) self.img_cpy = cv2.cvtColor(self.img_cpy, cv2.COLOR_RGB2BGR) self.tk_img = ImageTk.PhotoImage(image=Image.fromarray(self.img_cpy)) self.img_lbl.config(image=self.tk_img) def get_attributes(self): self.left_border_tag = (int(self.circle_center[0] - self.circle_radius), self.circle_center[1]) self.right_border_tag = (int(self.circle_center[0] + self.circle_radius), self.circle_center[1]) self.top_border_tag = (self.circle_center[0], int(self.circle_center[1] - self.circle_radius)) self.bottom_border_tag = (self.circle_center[0], int(self.circle_center[1] + self.circle_radius)) self.img_window.unbind("<ButtonPress-1>") self.img_window.unbind("<B1-Motion>") self.img_window.unbind("<ButtonRelease-1>") if (((self.circle_center[0] - self.circle_radius) < 0) or ((self.circle_center[0] + self.circle_radius) > self.w) or ((self.circle_center[1] - self.circle_radius) < 0) or ((self.circle_center[1] + self.circle_radius) > self.h)): ROIWarning(msg="ROI WARNING: The drawn circular ROI radius extends beyond the image. Please try again.", source=self.__class__.__name__) return False elif self.circle_radius == 0: ROIWarning(msg="ROI WARNING: The drawn circular ROI radius equals 0. Please try again.", source=self.__class__.__name__) return False else: return True
# img = cv2.imread(r"C:\Users\sroni\OneDrive\Desktop\Screenshot 2024-11-15 123805.png") # root = Toplevel() # root.title(DRAW_FRAME_NAME) # img_lbl = Label(root, name='img_lbl') # img_lbl.pack() # # img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # pil_image = Image.fromarray(img_rgb) # tk_image = ImageTk.PhotoImage(pil_image) # img_lbl.configure(image=tk_image) # img_lbl.image = tk_image # # _ = ROISelectorCircle(img_window=root) # root.mainloop() # circle_selector = ROISelectorCircle(path=r"C:\troubleshooting\mitra\test\503_MA109_Gi_CNO_0521.mp4") # circle_selector.run()