How can i fix colour detection in my code?

76 Views Asked by At
import pyautogui
import keyboard
import time

running = True

print("Script will start in 5 seconds.")
time.sleep(5)  # Wait for 5 seconds before starting

while running:
    keyboard.press_and_release('x')  # Press 'x' before every color detection

    # Capture the screen and get the color at the specified position
    screenshot = pyautogui.screenshot()
    target_color = (255, 0, 0)  # Replace with the RGB values of your target color
    target_position = (100, 100)  # Replace with the coordinates of the position to monitor

    # The pixel_color format is (red, green, blue, alpha)
    pixel_color = screenshot.getpixel(target_position)

    # Check if the pixel color matches the target color
    if pixel_color == target_color:
        time.sleep(1)  # Adjust this delay as needed to avoid rapid repeated key presses

    if keyboard.is_pressed('F10'):
        running = False
        print("Script stopped by user.")

I want it to press x, then wait until the colour is detected, and then press x and repeat those 2 actions, but it would either spam x or just press x once, and that's it.

I tried doing everything I could and researching, but I'm still fairly new, and I don't know how.

1

There are 1 best solutions below

0
phpjunkie On

A required package for pyautogui is pyscreeze. pyscreeze can get the color of the pixel for you.

pyscreeze.pixelMatchesColor(x: {__len__}, y: Any, expectedRGBColor: {__len__}, tolerance: int = 0) -> bool

Return True if the pixel at x, y matches the expected color of the RGB tuple, each color represented from 0 to 255, within an optional tolerance.

With this you don't need the 5 second delay for getting the pixel at the coordinates because pynput.keyboard.listener runs in it's own thread.

from time import sleep

import pynput.keyboard as kb
from pyscreeze import pixelMatchesColor, RGB

TERMINATE: bool = False

"""RGB is a collections.namedtuple. You can use regular tuple (255, 0, 0)"""
PIXEL: RGB = RGB(255, 0, 0)

kb.Key.x = 88

PRESSED = set()

"""I set this up this way incase you want to add control keys to the hotkeys.
Example: {kb.Key.ctrl_l, kb.Key.x}"""
HOTKEYS = [
    {kb.Key.x},
    {kb.Key.f10},
]


def on_key_pressed(key: int | kb.Key | kb.KeyCode):
    if isinstance(key, kb.KeyCode):
        key = key.vk

    if key not in PRESSED:
        PRESSED.add(key)

        """I set this up this way incase you want to add control keys to the hotkeys.
        Example: {kb.Key.ctrl_l, kb.Key.x}"""
        for hotkeys in HOTKEYS:
            if all(hotkey in PRESSED for hotkey in hotkeys):
                for hotkey in hotkeys:
                    if hotkey == key:
                        if hotkeys == HOTKEYS[0]:  # hotkey x for getting the color at pixel(x = 100, y = 100)
                            if pixelMatchesColor(x = 100, y = 100, expectedRGBColor = PIXEL):
                                pass
                        elif hotkeys == HOTKEYS[1]:  # hotkey f10 for terminating the script.
                            global TERMINATE
                            TERMINATE = True


def on_key_released(key: int | kb.Key | kb.KeyCode):
    if isinstance(key, kb.KeyCode):
        key = key.vk

    if key in PRESSED:
        PRESSED.remove(key)


keyboard: kb.Listener = kb.Listener(on_press = on_key_pressed, on_release = on_key_released)
keyboard.start()

while not TERMINATE:
    sleep(1 / 1000)

keyboard.stop()



if you decide you want to change the hotkeys for getting the pixel you can use this to get the key codes that aren't constants in pynput.keyboard.Key .

import pynput.keyboard as kb
from time import sleep


def on_key_press(key: int | kb.Key | kb.KeyCode):
    if isinstance(key, kb.KeyCode):
        key = key.vk

    print(key)


keyboard = kb.Listener(on_press = on_key_press)
keyboard.start()

while True:
    sleep(1 / 1000)```