How to use PIL floodfill in python?

Asked

Viewed 27 times

1

I am trying to color a bar using python’s PIL package. This is the original bar: inserir a descrição da imagem aqui

I would like to color the entire inner part with just one color. I tried to use the floodfill for that reason:

from PIL import Image, ImageDraw

im = Image.open('progress.jpeg')
width, height = im.size
center = (int(0.5*width), int(0.33* height))
yellow = (255, 255, 0, 255)
ImageDraw.floodfill(im, xy=center, value=yellow)
im.save('result.png')

And I got the following result:

inserir a descrição da imagem aqui

Initially, I imagined that the floodfill color all pixels that are between the specified width and height in the argument xy. As I took 1/3 of the height and half of the greeting, he painted yellow the inner area from left to right, from half. However, if I use 100% width, the program does not color anything. So obviously my interpretation is wrong.

How does floodfill work? How can I color the internal bar completely?

1 answer

1


Remember the function of the "bucket" of Paint? The floodfill works similarly: you pass a color and an XY point, and the PIL tries to "fill" the region around the XY point with the desired color.

Of course the cut-off point to define the boundary region of the fill will depend on your application - maybe you want the fill to pick up color regions similar but not identical the color of the region in which you added the color. You can control this with the argument thresh.

To color the entire bar in your case, I believe the simplest is to use the floodfill twice - passing an XY position within the green region, and an XY position within the black region. If all pixels in each region have the same intensity, you don’t even have to worry about the argument thresh.

Edit

I tested your image and the color along the bar is really not homogeneous - but if we use a thresh high enough, we can fill the bar fully. Below the example of code that does what you want:

im = Image.open('progress.jpeg')
width, height = im.size
green_region = (int(0.4*width), int(0.33*height))
black_region = (int(0.6*width), int(0.33* height))
yellow = (255, 255, 0, 255)
for region in (green_region, black_region):
    ImageDraw.floodfill(im, xy=region, value=yellow, thresh=150)
im.save('result.png')

Output: inserir a descrição da imagem aqui

The documentation of floodfill is here.

Examples:

  • Input image:

inserir a descrição da imagem aqui

  • Running your code in the image (uses the default argument thresh=0 - note the yellow pixel alone in the hat):

inserir a descrição da imagem aqui inserir a descrição da imagem aqui

  • Adding the argument thresh=30:

inserir a descrição da imagem aqui

  • Adding the argument thresh=100:

inserir a descrição da imagem aqui

Browser other questions tagged

You are not signed in. Login or sign up in order to post.