1

I have written the code that should allow me to go through the y-values of each column and return the RBG value for each pixel. I am trying to find all of the Pure White coloured pixels in my image. However for some reason I am presented with the error: "IndexError: image index out of range" when the final value in the first column has bee found. How can I move on to the next column?

My code looks like this:

from PIL import Image

pix = newimage2.load()
print(newimage2.size)
print(" ")

whitevalues = 0
x = 0
while x <= newimage2.width:
    y = 0
    while y <= newimage2.height:
        print(pix[x,y])
        if pix[x,y] == (255,255,255):
            whitevalues = whitevalues + 1
        y = y+1
    x = x+1
print(whitevalues)
v.coder
  • 1,510
  • 2
  • 12
  • 22
J.Kut
  • 29
  • 3

5 Answers5

1

Python is zero-indexed, i.e. if you have a list such as:

l = [1, 4, 7, 3, 6]

and you want to iterate through it with a while loop (a for-loop would be better but never mind), then you would have to loop while the index is less than the length of the list - so the index is never actually the length of the list, just up to 1 before.

The code for iterating over the list above would look something like:

i = 0
while i < len(l):
   print(l[i])
   i += 1

which would give you the output of:

1
4
7
3
6

The same logic applies to your image - which after all is essentially just a 2-dimensional list.

This means you need to correct the less than or equal (<=) comparators in your code to just less thans (<). Then your code should function how you would like it to.

So this would be the corrected code:

from PIL import Image
pix = newimage2.load()
print(newimage2.size)
print(" ")
whitevalues = 0
x = 0
while x < newimage2.width:
    y = 0
    while y < newimage2.height:
        print(pix[x,y])
        if pix[x,y] == (255,255,255):
            whitevalues += 1
        y += 1
    x += 1

print(whitevalues)

However, as I mentioned at the start, a for-loop would be better for this application as it will require less lines and is more Pythonic. So here is the code for a for-loop which you may find useful:

from PIL import Image
pix = newimage2.load()
print(newimage2.size)
print(" ")
whitevalues = 0
for row in newimage2
    for col in row:
        print(col)
        if col == (255,255,255):
            whitevalues += 1

print(whitevalues)

Or, if you wanted to be extremely pythonic, you could do this in a list-comprehension:

whitevalues = sum([1 for r in pix for c in r if c == 1])
Joe Iddon
  • 18,600
  • 5
  • 29
  • 49
0

You just need to change '<=' to '<' in the both while loops.

The main reason is that the index starts at 0. So if you look at the image size it will be (100,100) but if you try to access the pixel pix[100,100] it doesn't exist.

But pix[99,99] exists and corresponds to pix[100,100].

Cheers,

kaihami
  • 775
  • 6
  • 16
0

With zero-indexing, the last index is one less than the size. So you need to change your <= to <. Also, this question should have a index tag.

There are several ways you can use built-in functions to perform this task. See this question for examples. How to count the occurrence of certain item in an ndarray in Python? . These solutions will very likely be significantly faster.

Acccumulation
  • 2,309
  • 1
  • 5
  • 10
0

Instead of while loop try the below code:

[width, height] = newimage2.size 
for x in range(width):
    for y in range(height):
        cpixel = pixels[x, y]
        if(cpixel ==(255,255,255):
            whitevalues = whitevalues + 1

This will make sure that indexes are in range.

v.coder
  • 1,510
  • 2
  • 12
  • 22
0

The other answers get into why your code doesn't work, so this is just to show another approach to counting the white pixels:

from PIL import Image

image_path = '/path/to/image'
image = Image.open(image_path)
count = 0

# image.getdata() returns all the pixels in the image
for pixel in image.getdata():
    if pixel == (255, 255, 255):
        count += 1

print(count)