0

I made a script in python that detects color on the screen and clicks

import pyautogui
def get_pixel_colour(i_x, i_y):
   import PIL.ImageGrab
   return PIL.ImageGrab.grab().load()[i_x, i_y]



while(True):
   print (get_pixel_colour(400, 400))
   if (get_pixel_colour(400, 400)) == (75, 219, 106):
       pyautogui.click(400, 400)

I want to make this script faster since it only goes at about 50ms and i would like to get it to half of that. I'm fairly new to coding so I have no idea what to do to make it faster

  • 4
    First, I'd definitely move `import PIL.ImageGrab` out of the loop. – Captain Trojan Dec 04 '20 at 11:12
  • Then, you can store `get_pixel_colour(400, 400)` in a variable, and then use that variable for printing and comparison, so you don't have to call `PIL.ImageGrab.grab().load()[i_x, i_y]` twice. – Captain Trojan Dec 04 '20 at 11:13
  • 1
    also remove (or comment) all debug prints. Making a print on screen costs in terms of execution time [more here](https://stackoverflow.com/questions/13288185/performance-effect-of-using-print-statements-in-python-script) – Wippo Dec 04 '20 at 11:16
  • @Wippo One could wonder whether the `print` statement is actually a debug print or a desired feature of @SygMstr's script. – Captain Trojan Dec 04 '20 at 11:27
  • @CaptainTrojan I just wanted to point out that prints affect runtime and that when you want to measure the performance of a script you should comment the debug prints – Wippo Dec 04 '20 at 11:30
  • Does it help to set the `bbox` of [the image grab](https://pillow.readthedocs.io/en/stable/reference/ImageGrab.html)? – Karl Knechtel Dec 04 '20 at 12:01
  • @Sygmstr If any of the answers helped you, consider marking it as solved by pressing the checkbox next to it. – Ted Klein Bergman Dec 05 '20 at 17:40

2 Answers2

1

In conclusion:

import pyautogui
import PIL.ImageGrab

def get_pixel_colour(i_x, i_y):
    return PIL.ImageGrab.grab().load()[i_x, i_y]


while(True):
   c = get_pixel_colour(400, 400)
   print(c)
   if c == (75, 219, 106):
       pyautogui.click(400, 400)
Captain Trojan
  • 2,800
  • 1
  • 11
  • 28
0

First, cache the result from get_pixel_colour by storing it in a variable. This will reduce the time by half as it won't do a costly screenshot for both your print and comparison.

Secondly, remove the import from the function. It's a convention to always have the imports at the top of the file. It's also a bit more efficient as the import statement has to be evaluated multiple times if you keep it in the function. It won't import the module every time, but it still costs a small fraction of time.

Thirdly, you probably want to be more efficient about it and only grab the pixels you're interested in. grab takes an argument bbox which defines a bounding box of the pixels you want to grab.

import pyautogui
import PIL.ImageGrab


def get_pixel_colour(x, y):
    return PIL.ImageGrab.grab(bbox=(x, y, x+1, y+1)).load()[0, 0]


while True:
    colour = get_pixel_colour(400, 400)
    print(colour)
    if colour == (75, 219, 106):
        pyautogui.click(400, 400)
Ted Klein Bergman
  • 9,146
  • 4
  • 29
  • 50