在轮廓*内部*绘制一个填充颜色的填充多边形

问题描述 投票:0回答:1

我想绘制一个多边形作为轮廓并用特定的颜色填充它。对于

PIL
来说,这应该是一个足够简单的任务...不幸的是,
fill
参数产生的图像超出了轮廓...演示:

第 1 步,让我们清楚地展示我的轮廓应该是什么样子:

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')

这会产生下图:

这太棒了,我可以在 Photoshop 中确认我的角对应于指定的坐标。现在第 2 步,让我们使用

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')

注意此形状上出现的两个像素(下面突出显示)

这是不可接受的。填充的多边形不应超出轮廓。这是我期望的输出(在 Photoshop 中模拟):

问题

在一天结束时,我想编写一个函数,它将采用

n
顶点来绘制一个带有填充边界且不超出轮廓的干净多边形。另外,由于技术原因,我无法使用
matplotlib
,这意味着我无法使用
skimage.draw.polygon_perimeter
,但任何其他软件包(特别是利用
numpy
)将是最好的

python python-imaging-library
1个回答
0
投票

这是我当前的解决方案:使用

scipy.ndimage.binary_fill_holes
来填补这个洞。

import numpy as np
from scipy import ndimage
from PIL import Image, ImageDraw

vertices = [(44, 124),
            (50, 48),
            (74, 46),
            (73, 123),
            (44, 124)]
            
# draw the outline as a bitmap
outline = Image.new('1', (150, 150))
draw = ImageDraw.Draw(outline)
draw.line(vertices, fill=1, width=1)
outline = np.array(outline)

# fill with ndimage.binary_fill_holes
fill = ndimage.binary_fill_holes(outline)

# remove outline from fill using a logical "and"
fill = fill & ~outline

# create the final image
canvas = np.zeros((150,150,3), dtype=np.uint8)
canvas[fill == True] = [255, 255, 255] # fill with white
canvas[outline == True] = [0, 0, 255] # outline is blue

final = Image.fromarray(canvas)
final.save('final.png')

结果:

© www.soinside.com 2019 - 2024. All rights reserved.