I want to draw a polygon as an outline and fill it with a specific color. This should be an easy enough task for PIL
… Unfortunately the fill
argument produces an image that bleeds out of the outline… Demonstration:
Step 1, lets show clearly what my outline should look like:
from PIL import Image, ImageDraw
vertices = [(44, 124),
(50, 48),
(74, 46),
(73, 123),
(44, 124)]
# draw as an outline
image = Image.new('RGB', (150, 150), 'black')
draw = ImageDraw.Draw(image)
draw.line(vertices, fill='blue', width=1)
image.save(r'outline.png')
This produces the image below:
This is great, and i can confirm in Photoshop that my corners corresponds to the specified coordinates. Now step 2, lets do the same using the polygon
function and draw a filled polygon:
# draw as a filled polygon
image = Image.new('RGB', (150, 150), 'black')
draw = ImageDraw.Draw(image)
draw.polygon(vertices, fill='white', outline='blue', width=1)
image.save(r'filled.png')
Notice the two pixels appearing on this shape? These white pixels are at (75, 46) and (43, 124) which are outside the boundary.
This is not acceptable. The filled polygon should not rasterize beyond its outline. Here is the desired output I would have expected (mocked up in Photoshop):
QUESTION
At the end of the day, I want to write a function which will take n
vertices to draw a clean polygon with a filled boundary the does not exceed the outline. Also, for technical reasons I cannot use matplotlib
, which means I cannot use skimage.draw.polygon_perimeter
because it needs matplotlib
. Any other package (especially if leveraging numpy
) would be best.
2
Answers
Here's my current solution: use
scipy.ndimage.binary_fill_holes
to fill the hole.Result:
This works for now, but I need to compare with
ImageDraw
for speed as i need to run this millions of times.The clear answer for speed:
opencv-python