Use this code as context:
"
import customtkinter as ctk
from CTkToolTip import CTkToolTip
import pyautogui
import threading
import random
import time
import cv2
import numpy as np
import keyboard

# Custom CTkButton creation to workaround early press issue when not released
def CreateCTkButton(self, text, command, **kwargs):
    button = ctk.CTkButton(self, text=text, **kwargs)

    def on_press(event):
        if button.cget("state") == "normal":
            button.pressed = True

    def on_motion(event):
        if button.cget("state") == "normal":
            x, y = button.winfo_x(), button.winfo_y()
            w, h = button.winfo_width(), button.winfo_height()
            if not (x <= event.x_root <= x + w and y <= event.y_root <= y + h):
                button.pressed = False

    def on_release(event):
        if button.cget("state") == "normal" and hasattr(button, 'pressed') and button.pressed:
            button.pressed = False
            command()

    def set_cursor():
        if button.cget("state") == "normal":
            button.configure(cursor="hand2")
        else:
            button.configure(cursor="arrow")
        button.after(100, set_cursor)

    button.bind("<ButtonPress-1>", on_press)
    button.bind("<B1-Motion>", on_motion)
    button.bind("<ButtonRelease-1>", on_release)

    set_cursor()
    return button

class BlumAutoClickerApp:
    def __init__(self, root):
        self.root = root
        ctk.set_appearance_mode("System")
        ctk.set_default_color_theme("green")

        self.app_version = 1.0
        self.root.title("Blum AutoClicker " + str(self.app_version))
        self.root.geometry("360x670")
        self.root.resizable(False, False)

        # Capturing areas
        self.capture_area = None
        self.game_window_area = None
        self.start_button_area = None

        # Settings
        self.repeat_times = None
        self.human_speed = ctk.BooleanVar(value=True)
        self.pick_bombs = ctk.BooleanVar(value=True)

        self.is_running = False

        # Unified button style
        self.button_style = {
            'font': ("Arial", 18),
            'width': 300,
            'height': 45 
        }

        # Define color ranges for detection
        self.color_ranges = {
            'snowflake': (np.array([0, 128, 0]), np.array([0, 255, 0])),
            'ice_crystal': (np.array([0, 200, 200]), np.array([255, 255, 255])),
            'bomb': (np.array([0, 0, 200]), np.array([100, 100, 255])),
        }

        # UI Elements
        self.create_widgets()
        self.update_button_states()

        # Register global hotkeys
        keyboard.add_hotkey('alt+s', self.start_clicker)
        keyboard.add_hotkey('alt+x', self.stop_clicker)

    def create_widgets(self):
        ctk.CTkLabel(self.root, text=self.root.title(), font=("Tahoma", 25, 'bold')).pack(pady=10)
        ctk.CTkLabel(self.root, text="Copyright (C) 2024 Vusal Bagirov", font=("Tahoma", 13)).pack(side=ctk.BOTTOM, pady=10)

        self.start_button = CreateCTkButton(self.root, "Start AutoClicker", self.start_clicker, **self.button_style)
        self.start_button.pack(pady=5)

        self.stop_button = CreateCTkButton(self.root, "Stop AutoClicker", self.stop_clicker, **self.button_style)
        self.stop_button.pack(pady=5)

        self.capture_area_button = CreateCTkButton(self.root, "Define Capture Area", self.define_capture_area, **self.button_style)
        self.capture_area_button.pack(pady=5)
        CTkToolTip(self.capture_area_button, delay=0, message="Define the area to capture")

        self.capture_area_label = ctk.CTkLabel(self.root, text="Capture Area: (0, 0, 0, 0)", font=("Arial", 16))
        self.capture_area_label.pack(pady=5)

        self.game_window_area_button = CreateCTkButton(self.root, "Define Game Window Area", self.define_game_window_area, **self.button_style)
        self.game_window_area_button.pack(pady=5)
        CTkToolTip(self.game_window_area_button, delay=0, message="Define the game window area")

        self.game_window_area_label = ctk.CTkLabel(self.root, text="Game Window Area: (0, 0, 0, 0)", font=("Arial", 16))
        self.game_window_area_label.pack(pady=5)

        self.start_button_area_button = CreateCTkButton(self.root, "Define Start Button Area", self.define_start_button_area, **self.button_style)
        self.start_button_area_button.pack(pady=5)
        CTkToolTip(self.start_button_area_button, delay=0, message="Define the start button area")

        self.start_button_area_label = ctk.CTkLabel(self.root, text="Start Button Area: (0, 0)", font=("Arial", 16))
        self.start_button_area_label.pack(pady=5)

        self.human_speed_toggle = ctk.CTkSwitch(self.root, text="Human Speed", font=("Arial", 16), variable=self.human_speed, command=self.update_human_speed_info)
        self.human_speed_toggle.pack(pady=5)
        CTkToolTip(self.human_speed_toggle, delay=0, message="Human Speed")

        self.pick_bombs_toggle = ctk.CTkSwitch(self.root, text="Pick Bombs", font=("Arial", 16), variable=self.pick_bombs, command=self.update_pick_bombs_info)
        self.pick_bombs_toggle.pack(ipadx=6, pady=5)
        CTkToolTip(self.pick_bombs_toggle, delay=0, message="Pick Bombs")
        
        repeat_frame = ctk.CTkFrame(self.root, fg_color='transparent')
        repeat_frame.pack(pady=5)
        ctk.CTkLabel(repeat_frame, text="Repeat times:", font=("Arial", 16)).pack(side=ctk.LEFT)
        self.repeat_times_entry = ctk.CTkEntry(repeat_frame, placeholder_text="Until stopped", width=100)
        self.repeat_times_entry.pack(side=ctk.LEFT, padx=(5, 0))
        self.repeat_times_entry.bind("<Return>", lambda event: self.update_repeat_times_info())
        CTkToolTip(self.repeat_times_entry, delay=0, message="Repeat times")

        ctk.CTkLabel(self.root, text="Appearance Mode:", font=("Arial", 16)).pack(pady=5)
        self.appearance_mode_optionemenu = ctk.CTkOptionMenu(self.root,
            values=["Light", "Dark", "System"],
            command=self.change_appearance_mode
        )
        self.appearance_mode_optionemenu.set("System")
        self.appearance_mode_optionemenu.pack(pady=5)

        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def change_appearance_mode(self, appearance_mode: str):
        ctk.set_appearance_mode(appearance_mode)
        print(f"Appearance mode set to: {appearance_mode}")

    def define_capture_area(self):
        self.select_area("capture")

    def define_game_window_area(self):
        self.select_area("game_window")

    def select_area(self, area_type):
        if hasattr(self, 'overlay') and self.overlay.winfo_exists():
            return

        self.overlay = ctk.CTkToplevel(self.root)
        self.overlay.attributes('-alpha', 0.4)
        self.overlay.attributes('-fullscreen', True)
        self.overlay.attributes('-topmost', True)

        self.canvas = ctk.CTkCanvas(self.overlay, highlightthickness=0)

        if area_type == "capture":
            self.canvas.configure(bg='#87ceeb')
        elif area_type == "game_window":
            self.canvas.configure(bg='#66cdaa')

        self.canvas.pack(fill=ctk.BOTH, expand=True)

        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
        self.canvas.bind("<ButtonRelease-1>", lambda event: self.on_button_release(event, area_type))

        self.start_x = None
        self.start_y = None
        self.rect = None

    def define_start_button_area(self):
        self.select_point("start_button")

    def on_button_press(self, event):
        self.start_x = event.x
        self.start_y = event.y
        self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='#0066cc', fill='#0078d7', width=2)

    def on_mouse_drag(self, event):
        self.canvas.coords(self.rect, self.start_x, self.start_y, event.x, event.y)

    def on_button_release(self, event, area_type):
        end_x, end_y = event.x, event.y
        if area_type == "capture":
            self.capture_area = (min(self.start_x, end_x), min(self.start_y, end_y), max(self.start_x, end_x), max(self.start_y, end_y))
            print("Capture area defined:", self.capture_area)
            self.capture_area_label.configure(text=f"Capture Area: {self.capture_area}")
        elif area_type == "game_window":
            self.game_window_area = (min(self.start_x, end_x), min(self.start_y, end_y), max(self.start_x, end_x), max(self.start_y, end_y))
            print("Game window area defined:", self.game_window_area)
            self.game_window_area_label.configure(text=f"Game Window Area: {self.game_window_area}")

        self.overlay.destroy()
        self.update_button_states()

    def select_point(self, area_type):
        if hasattr(self, 'overlay') and self.overlay.winfo_exists():
            return
            
        self.overlay = ctk.CTkToplevel(self.root)
        self.overlay.attributes('-alpha', 0.4)
        self.overlay.attributes('-fullscreen', True)
        self.overlay.attributes('-topmost', True)
        self.overlay.bind("<ButtonPress-1>", self.on_point_select)

        self.overlay.mainloop()

    def on_point_select(self, event):
        self.start_button_area = (event.x, event.y)
        print("Start button area defined at:", self.start_button_area)
        self.start_button_area_label.configure(text=f"Start Button Area: {self.start_button_area}")
        self.overlay.destroy()
        self.update_button_states()

    def update_human_speed_info(self):
        print(f"Human Speed changed to: {self.human_speed.get()}")

    def update_pick_bombs_info(self):
        print(f"Pick Bombs changed to: {self.pick_bombs.get()}")

    def update_repeat_times_info(self):
        if self.repeat_times_entry.get().isdigit():
            self.repeat_times = int(self.repeat_times_entry.get())
            print(f"Repeat times changed to: {self.repeat_times}")
        else:
            self.repeat_times = None

    def start_clicker(self):
        if not self.is_running:  # Ensure the clicker starts only if it's not already running
            self.is_running = True
            self.repeat_times = self.repeat_times_entry.get()
            if self.repeat_times.isdigit():
                self.repeat_times = int(self.repeat_times)
            else:
                self.repeat_times = None

            try:
                threading.Thread(target=self.click_loop).start()
            except Exception as e:
                print(f"Error starting clicker: {e}")
            self.update_button_states()

    def stop_clicker(self):
        self.is_running = False
        self.update_button_states()

    def click_loop(self):
        while self.is_running:
            if self.check_for_game_elements():
                if self.human_speed.get():
                    time.sleep(random.uniform(0.1, 0.5))

                self.click_on_snowflakes()
            else:
                ctk.CTkMessageBox.showinfo("No Game Elements", "No game elements found on the screen.")

            if self.repeat_times is not None:
                self.repeat_times -= 1
                if self.repeat_times <= 0:
                    self.stop_clicker()

            time.sleep(0.05)  # Brief pause to optimize performance

    def get_screenshot(self):
        return cv2.cvtColor(np.array(pyautogui.screenshot()), cv2.COLOR_RGB2BGR)

    def check_for_game_elements(self):
        screen = self.get_screenshot()
        for lower, upper in self.color_ranges.values():
            mask = cv2.inRange(screen, lower, upper)
            if np.any(mask):
                return True
        return False

    def click_on_snowflakes(self):
        screen = self.get_screenshot()
        for element, (lower, upper) in self.color_ranges.items():
            mask = cv2.inRange(screen, lower, upper)
            contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            for contour in contours:
                if cv2.contourArea(contour) > 10:
                    M = cv2.moments(contour)
                    if M["m00"] != 0:
                        cX = int(M["m10"] / M["m00"])
                        cY = int(M["m01"] / M["m00"])
                        pyautogui.click(cX, cY)
                        print(f"Clicked on {element} at: ({cX}, {cY})")
                        return

                        # Bomb clicking logic, if enabled
                if element == 'bomb' and self.pick_bombs.get():
                    if random.random() < 0.1:  # 10% chance to click on bombs
                        pyautogui.click(cX, cY)
                        print(f"Clicked on bomb at: ({cX}, {cY})")
                        return

    def update_button_states(self):
        if self.capture_area and self.game_window_area and self.start_button_area:
            self.start_button.configure(state='normal')
        else:
            self.start_button.configure(state='disabled')

        if self.is_running:
            self.stop_button.configure(state='normal')
        else:
            self.stop_button.configure(state='disabled')

    def on_closing(self):
        self.stop_clicker()
        keyboard.unhook_all()
        self.root.destroy()

if __name__ == "__main__":
    root = ctk.CTk()
    app = BlumAutoClickerApp(root)
    root.mainloop()
"

Just for you information and context, what also can help: this is autoclicker app (not finished yet) on python for Blum Drop game. There is a drop game in which players during 30 seconds pick falling snowflakes and earn points for it. Also there are two elements: ice crystal that freezes the game for a while and allows the player to collect snowflakes on the screen; and bombs that explode and reset all points in the current game if the player accidentally clicks on them.