I am doing some pixel operations in Python, which obviously uses a lot of processing power and makes the program extremely slow. I have these nested loops:

 for x in range(-1, 2): #for the left, center and right row of pixels next to this pixel
        for y in range(-1, 2): #for the top and bottom row of pixels nwxt to this pixel
            if x == 0 and y == 0: #exclude this pixel
                for pix in allPixels: #for every existing pixel
                    surroundingpixel = False
                    pix_info = pix.info() #get the pixel information
                    if pix_info[0] == self.x + x and pix_info[1] == self.y + y: #if there is a pixel in this position
                        self.surr.append(pix) #add the pixel to the list of surrounding pixels
                        surroundingpixel = True
                if not surroundingpixel:
    return self.surr

If there are a lot of pixels on the screen the program slows down massively My full code is quite a bit longer, but I can add things to this post as necessary.

I was hoping someone could help me make this code more efficient. I've been using nested loops and using cProfiler, 86% of processing time is taken up by this function. Any help making this block of code more efficient would be much appreciated.

The full code can be found here if needed.

  • 2
    \$\begingroup\$ What is this pixel operation supposed to accomplish? \$\endgroup\$ – Kelson Ball May 18 '18 at 22:27
  • \$\begingroup\$ @KelsonBall Ball It returns a list that has a pixel objext in the list if there is a pixels surrounding the pixel and a 0 if there isn't. The i use that to see if the pixel next to it is free or not \$\endgroup\$ – Thomas Ayling May 18 '18 at 22:29
  • \$\begingroup\$ What is allPixels (a list perchance)? \$\endgroup\$ – vnp May 18 '18 at 22:32
  • 1
    \$\begingroup\$ Make it a dictionary indexed by (x, y). As posted I am afraid the question is off-topic here. \$\endgroup\$ – vnp May 18 '18 at 22:34
  • 2
    \$\begingroup\$ I feel you are doing lot of unnecessary work, your question lacks context and your code is not testable as it is. \$\endgroup\$ – Billal Begueradj May 19 '18 at 5:31

As noted, there is not quite enough information about the inputs to this function to give confident advice.

for pix in allPixels: #for every existing pixel

This is almost certainly the wrong way of doing this, and the cause of most of your slowness. Rather than checking each pixel and confirming whether it is in the location you're looking at, use a data structure which allows you to select the desired pixel immediately. @vnp suggests using a dict. You could also use a set or just a 2D array matching the coordinates. Given that this is about pixels, a 2D array is the most natural representation. I'd use it unless the pixels in question are very sparse, in which case I'd maintain a set.

If this still isn't fast enough, you'd probably want to avoid using Python to loop through each pixel. That's not to say don't write your program in Python. There are python libraries like numpy that let you operate on whole arrays at once. Under the hood, they use optimised C functions and exploit tricks like SIMD vectorisation to do things crazy fast.

See this previous question for an example of how to do so. It's about Conway's Game of Life, which is all about counting neighbouring pixels. You should be able to adapt it.

| improve this answer | |
  • \$\begingroup\$ Yeah, i've made a program about game of life but with a smaller grid/higher resolutions than just pixels. I'll have a look thanks because i still have to loop through 9 times for each pixel and that means if there are 3000 pixels, which is nowhere near the whole screen resolution, the program has to iterate 27000 odd times each frame. \$\endgroup\$ – Thomas Ayling May 20 '18 at 16:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.