Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fill in a hollow shape using Python and pillow (PIL)

I am trying to write a method that will fill in a given shape so that it becomes solid black.

Example: This octagon which initially is only an outline, will turn into a solid black octagon, however this should work with any shape as long as all edges are closed.

Octagon

def img_filled(im_1, im_2):
    img_fill_neg = ImageChops.subtract(im_1, im_2)
    img_fill = ImageOps.invert(img_fill_neg)
    img_fill.show()

I have read the docs 10x over and have found several other ways to manipulate the image, however I can not find an example to fill in a pre-existing shape within the image. I see that using floodfill() is an option, although I'm not sure how to grab the shape I want to fill.

Note: I do not have access to any other image processing libraries for this task.

like image 927
Thomas Eggenberger Avatar asked Sep 06 '17 20:09

Thomas Eggenberger


1 Answers

There are several ways of doing this. You could do as I do here, and fill all the areas outside the outline with magenta, then make everything that is not magenta into black, and then revert all artificially magenta-coloured pixels to white.

I have interspersed intermediate images in the code, but you can just grab all the bits of code and collect them together in order to have a working lump of code.

#!/usr/bin/env python3

from PIL import Image, ImageDraw
import numpy as np

# Open the image
im = Image.open('octagon.png').convert('RGB')

# Make all background (exterior to octagon) pixels magenta (255,0,255)
ImageDraw.floodfill(im,xy=(0,0),value=(255,0,255),thresh=200)
# DEBUG
im.save('intermediate.png')

enter image description here

# Make everything not magenta black
n  = np.array(im)
n[(n[:, :, 0:3] != [255,0,255]).any(2)] = [0,0,0]

# Revert all artifically filled magenta pixels to white
n[(n[:, :, 0:3] == [255,0,255]).all(2)] = [255,255,255]

Image.fromarray(n).save('result.png')

enter image description here

Or, you could fill all the background with magenta, then locate a white pixel and flood-fill with black using that white pixel as a seed. The method you choose depends on the expected colours of your images, and the degree to which you wish to preserve anti-aliasing and so on.

like image 164
Mark Setchell Avatar answered Sep 30 '22 20:09

Mark Setchell