How to count bright pixels in an image?

Viewed 8608

How do I make this code print the total number of bright pixels that are over 200:

from PIL import Image
img = input("File name: ")
img = Image.open(img);
for y in range(img.height):
  for x in range(img.width):
    pixel = img.getpixel((x, y))
    if pixel >= 200:
      print(pixel,"pixels are bright.")

Right now it's printing every single pixel that is over 200 on new lines, but I just want one line that prints the total like this:

File name: slippers.png
121081 pixels are bright.      
4 Answers

You don't need loops at all for this. Simply create a mask returning which pixels are above the threshold, and sum the mask.

With numpy

You just need to convert the img from a PIL Image to a numpy array, which you can do with np.array(img). Then create a boolean mask for whenever the pixels are above your threshold, np.array(img) >= 200. This will create an array of the same size as your image with a True or False in each pixel location for whether it meets the criteria. Then if you np.sum() the resulting image, it will convert True to 1 and False to 0, so summing will give the total number of pixels which met the criteria. All of this in one line:

bright_count = np.sum(np.array(img) >= 200)

Pure PIL

For a purely PIL solution that doesn't use numpy, you can use the point() method of the Image class. See this question/answer for a good discussion of the method. The point() method takes in a function which assigns new values to a pixel. Here I've just assigned a value of 1 whenever it's above the threshold. Then I've grabbed just the data from the Image type with the getdata() method, and summed the data with the Python sum() function.

bright_count = sum(img.point(lambda pix: 1 if pix>=thresh else 0).getdata())

Just count the pixels before printing:

from PIL import Image
img = input("File name: ")
img = Image.open(img);
count = 0
for y in range(img.height):
  for x in range(img.width):
    pixel = img.getpixel((x, y))
    if pixel >= 200:
      count += 1

print(count,"pixels are bright.")

You can use the getcolors() function from PIL image, this function return a list of tuples with colors found in image and the amount of each one. I'm using the following function to return a dictionary with color as key, and counter as value.

from PIL import Image

def getcolordict(im):
    w,h = im.size
    colors = im.getcolors(w*h)
    colordict = { x[1]:x[0] for x in colors }
    return colordict

im = Image.open('image.jpg')
colordict = getcolordict(im)

# get the amount of black pixels in image
# in RGB black is 0,0,0
black_pixels_count = colordict.get((0,0,0))

# get the amount of white pixels in image
# in RGB white is 255,255,255
white_pixels_count = colordict.get((255,255,255))  

You can try this one too (Python 3):

from PIL import Image

imgFile = input("File name: ")
img = Image.open(imgFile);
pixels = img.getdata()
total = len(list(filter(lambda i: i >= (200,200,200), pixels)))
print("There are %d bright pixels" % total)

You can use the getdata() method to take all pixels at once end then you can filter the ones which are above the desired value. In Python 2, you can simply write i >= 200.

Related