pythonimagecolorsdetection

Python Script Clicks on Blue Pixels Instead of Red


I’ve written a Python script that captures screenshots and clicks on specific pixels based on their color. The goal is to click on red pixels, but for some reason, it’s clicking on blue pixels instead.

Here is the code:

import mss
import pyautogui
import numpy as np
import keyboard

top, left, width, height = 521, 1071, 451, 443
target_color = (255, 0, 0)  

def click_at(x, y):
    pyautogui.click(x, y)  

def is_target_color(pixel):
   
    tolerance = 20
    r, g, b = pixel[:3]
    return abs(r - target_color[0]) < tolerance and abs(g - target_color[1]) < tolerance and abs(b - target_color[2]) < tolerance

def create_border_mask(width, height, border_thickness):
    mask = np.zeros((height, width), dtype=bool)
    mask[:border_thickness, :] = True
    mask[-border_thickness:, :] = True
    mask[:, :border_thickness] = True
    mask[:, -border_thickness:] = True
    return mask

border_thickness = 2
border_mask = create_border_mask(width, height, border_thickness)
screenshot_count = 0

def main():
    global screenshot_count
    with mss.mss() as sct:
        monitor = {"top": top, "left": left, "width": width, "height": height}

        while True:
            if keyboard.is_pressed("ctrl+1"):
                print("Stopping...")
                break

            screenshot = sct.grab(monitor)
            screenshot_count += 1
            print(f"Screenshot taken: {screenshot_count}")

            img = np.array(screenshot)

            found = False
            for y in range(height):
                for x in range(width):
                    if border_mask[y, x]:
                        pixel = img[y, x][:3]
                        if is_target_color(pixel):
                            click_at(left + x, top + y) 
                            found = True
                            break
                        else:
                            
                            pass
                if found:
                    break

    print(f"Total screenshots taken: {screenshot_count}")

if __name__ == "__main__":
    main()

I’ve tried adjusting the color matching logic, but I can’t seem to find the root cause of this issue.

As a newcomer to Python, I’m seeking help from the community to understand why the script isn’t accurately detecting red pixels. Any insights or suggestions would be greatly appreciated! (I want the code to run as fast as possible)


Solution

  • OpenCV by default use BGR Colour Space (due to historical reasons, see Why OpenCV Using BGR Colour Space Instead of RGB for details), you should either follow that in this line

    r, g, b = pixel[:3]
    

    or convert to RGB before processing, OpenCV: Changing Colorspaces does describe how to do that