I wrote a quick python script to return the average colour of rectangles surrounding the perimeter of my screen. (The end goal here is to have RGB LED strips surrounding my moni
A quick win could be to use a resize
operation (in PIL) (you may use simple interpolation for speed) to a 5x5 image instead of averaging the regions, e.g.:
myimg = ImageGrab.grab()
resized = myimg.resize((5, 5), Image.NEAREST)
This should yield approximately the same effect as doing the averaging work yourself.
Not really sure about the speed of PIL's ImageGrab (and how it compares to autopy
) though, but it's easy enough to try and find out.
Use the Python Imaging Library. From the docs (in the Image module):
getcolors
im.getcolors() => a list of (count, color) tuples or None
im.getcolors(maxcolors) => a list of (count, color) tuples or None
(New in 1.1.5) Returns an unsorted list of (count, color) tuples, where the count is the number of times the corresponding color occurs in the image.
The Image module also contains a crop() method you can use to get each rectangle to plug into getcolors(). You can take a weighted average from that easily.
It should be much faster than running the loop manually in python. I'm not sure if it's fast enough to use in real time, but you will get a dramatic speed boost. You could also take the screenshot a few times per second, since odds are that sending signals to the LEDs at 60 fps vs 10 fps won't be particularly noticeable. Don't look at it as "limited to 12.8 FPS", look at it as "can only update the LEDs once every 5 frames", which shouldn't be a noticeable difference.
EDIT: If you're really interested in further optimization here, I think you'll find Fastest way to take a screenshot with python on windows quite helpful.
To speed up a resize operation you can do it in two steps. Use NEAREST for the first one to cut down the number of pixels in the fastest way possible, then ANTIALIAS to merge those into a representative sample. It's equivalent to the step size you experimented with earlier, done with PIL functions.
PIL.ImageGrab.grab().resize((150, 100), PIL.Image.NEAREST).resize((15, 10), PIL.Image.ANTIALIAS)