blaylockbk
blaylockbk

Reputation: 3321

Python - find out how much of an image is black

I am downloading satellite pictures like this satellite_image
(source: u0553130 at home.chpc.utah.edu)

Since some images are mostly black, like this one, I don't want to save it.

How can I use python to check if the image is more than 50% black?

Upvotes: 7

Views: 16525

Answers (4)

Hugo
Hugo

Reputation: 29344

The thorough way is to count the pixels using something like PIL, as given in the other answers.

However, if they're all compressed images, you may be able to check the file size, as images with lots of plain-colour areas should compress a lot more than ones with variation like the cloud cover.

With some tests, you could at least find a heuristic of which images with lots of cloud you know you can instantly discard without expensive looping over their pixels. Others closer to 50% can be checked pixel by pixel.

Additionally, when iterating over the pixels, you don't need to count all the black pixels, and then check if at least 50% are black. Instead, stop counting and discard as soon as you know at least 50% are black.

A second optimisation: if you know the images are generally mostly cloudy rather than mostly black, go the other way. Count the number of non-black pixels, and stop and keep the images as soon as that crosses 50%.

Upvotes: 4

xnx
xnx

Reputation: 25518

You're dealing with gifs which are mostly grayscale by the look of your example image, so you might expect most of the RGB components to be equal.

Using PIL:

from PIL import Image
im = Image.open('im.gif')
pixels = im.getdata()          # get the pixels as a flattened sequence
black_thresh = 50
nblack = 0
for pixel in pixels:
    if pixel < black_thresh:
        nblack += 1
n = len(pixels)

if (nblack / float(n)) > 0.5:
    print("mostly black")

Adjust your threshold for "black" between 0 (pitch black) and 255 (bright white) as appropriate).

Upvotes: 12

Andy
Andy

Reputation: 50560

Utilizing your test image, the most common color has an RGB value of (1, 1, 1). This is very black, but not exactly black. My answer utilizes the PIL library, webcolors and a generous helping of code from this answer.

from PIL import Image
import webcolors

def closest_color(requested_color):
    min_colors = {}
    for key, name in webcolors.css3_hex_to_names.items():
        r_c, g_c, b_c = webcolors.hex_to_rgb(key)
        rd = (r_c - requested_color[0]) ** 2
        gd = (g_c - requested_color[1]) ** 2
        bd = (b_c - requested_color[2]) ** 2
        min_colors[(rd + gd + bd)] = name
    return min_colors[min(min_colors.keys())]

def get_color_name(requested_color):
    try:
        closest_name = actual_name = webcolors.rgb_to_name(requested_color)
    except ValueError:
        closest_name = closest_color(requested_color)
        actual_name = None
    return actual_name, closest_name

if __name__ == '__main__':
    lt = Image.open('test.gif').convert('RGB').getcolors()
    lt.sort(key=lambda tup:tup[0], reverse=True)
    actual_name, closest_name = get_color_name(lt[0][4])
    print lt[0], actual_name, closest_name

Output:

(531162, (1, 1, 1)) None black

In this case, you'd be interested in the closest_name variable. The first (lt[0]) is showing you the most common RGB value. This doesn't have a defined web color name, hence the None for actual_name


Explanation:

This is opening the file you've provided, converting it to RGB and then running PIL's getcolors method on the image. The result of this is a list of tuples in the format (count, RGB_color_value). I then sort the list (in reverse order). Utilizing the functions from the other answer, I pass the most common RGB color value (now the first tuple in the list and the RBG is the second element in the tuple).

Upvotes: 0

0xmax
0xmax

Reputation: 543

  • Load image
  • Read each pixel and increment result if pixel = (0,0,0)
  • If result =< (image.width * image.height)/2
  • Save image

Or check if it's almost black by returning true if your pixel R (or G or B) component is less that 15 for example.

Upvotes: 0

Related Questions