Source code for simba.roi_tools.roi_selector_rectangle_tkinter

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

from tkinter import *
from typing import Tuple

import cv2
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 ROISelector: """ A class to allow users to interactively select a Region of Interest (ROI) rectangle from an image displayed in a Tkinter window. .. video:: tutorials_rst/img/roi/draw_rectangle.webm :width: 900 :loop: :muted: :align: center .. seealso:: For OpenCV based method, see :func:`simba.video_processors.roi_selector.ROISelector` :param img_window (Toplevel): The Tkinter Toplevel window containing the image. :param thickness (int): The thickness of the ROI selection rectangle. :param clr (Tuple[int, int, int]): The color of the ROI selection 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.roi_start, self.roi_end = None, None self.selecting_roi, self.complete = False, False self.img_window.bind("<ButtonPress-1>", self.on_mouse_down) self.img_window.bind("<B1-Motion>", self.on_mouse_drag) self.img_window.bind("<ButtonRelease-1>", self.on_mouse_up) def on_mouse_down(self, event): self.roi_start = (event.x, event.y) self.roi_end = (event.x, event.y) self.selecting_roi = True # def on_mouse_drag(self, event): if self.selecting_roi: self.roi_end = (event.x, event.y) self.img_cpy = self.img.copy() cv2.rectangle(self.img_cpy, self.roi_start, self.roi_end, self.clr, self.thickness) self.update_image(self.img_cpy) def on_mouse_up(self, event): self.roi_end = (event.x, event.y) self.selecting_roi = False self.complete = True # def update_image(self, img): img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) pil_image = Image.fromarray(img_rgb) tk_image = ImageTk.PhotoImage(pil_image) self.img_lbl.configure(image=tk_image) self.img_lbl.image = tk_image def get_attributes(self): self.top_left = min(self.roi_start[0], self.roi_end[0]), min(self.roi_start[1], self.roi_end[1]) self.bottom_right = max(self.roi_start[0], self.roi_end[0]), max(self.roi_start[1], self.roi_end[1]) if self.top_left[0] < 0: self.top_left = (0, self.top_left[1]) if self.top_left[1] < 0: self.top_left = (self.top_left[0], 0) if self.bottom_right[0] < 0: self.bottom_right = (0, self.bottom_right[1]) if self.bottom_right[1] < 0: self.bottom_right = (self.bottom_right[0], 0) if self.bottom_right[0] > self.w: self.bottom_right = (self.w, self.bottom_right[1]) if self.bottom_right[1] > self.h: self.bottom_right = (self.bottom_right[0], self.h) self.width = self.bottom_right[0] - self.top_left[0] self.height = self.bottom_right[1] - self.top_left[1] self.center = (int(self.top_left[0] + (self.width / 2)), int(self.top_left[1] + (self.height / 2))) self.bottom_right_tag = (int(self.top_left[0] + self.width), int(self.top_left[1] + self.height)) self.top_right_tag = (int(self.top_left[0] + self.width), int(self.top_left[1])) self.bottom_left_tag = (int(self.top_left[0]), int(self.top_left[1] + self.height)) self.top_tag = (int(self.top_left[0] + self.width / 2), int(self.top_left[1])) self.right_tag = (int(self.top_left[0] + self.width), int(self.top_left[1] + self.height / 2)) self.left_tag = (int(self.top_left[0]), int(self.top_left[1] + self.height / 2)) self.bottom_tag = (int(self.top_left[0] + self.width / 2), int(self.top_left[1] + self.height)) self.img_window.unbind("<ButtonPress-1>") self.img_window.unbind("<B1-Motion>") self.img_window.unbind("<ButtonRelease-1>") if (self.width == 0 and self.height == 0) or (self.width + self.height + self.top_left[0] + self.top_left[1] == 0): ROIWarning(msg="ROI WARNING: ROI height and width are both 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 # # _ = ROISelector(img_window=root) # root.mainloop()