SciPy 创建二维多边形掩码

64 投票
7 回答
68614 浏览
提问于 2025-04-16 03:46

我需要用标准的Python库创建一个numpy的二维数组,这个数组要表示一个多边形的二进制掩码。

  • 输入:多边形的顶点,图像的尺寸
  • 输出:多边形的二进制掩码(numpy二维数组)

(更大的背景:我想用scipy.ndimage.morphology.distance_transform_edt来获取这个多边形的距离变换。)

有没有人能教我怎么做这个?

7 个回答

27

关于乔的评论,有个更新。自从那条评论发布以来,Matplotlib的接口发生了变化,现在你需要使用一个叫做 matplotlib.path 的子模块提供的方法。

下面是可以正常工作的代码。

import numpy as np
from matplotlib.path import Path

nx, ny = 10, 10
poly_verts = [(1,1), (5,1), (5,9),(3,2),(1,1)]

# Create vertex coordinates for each grid cell...
# (<0,0> is at the top left of the grid in this system)
x, y = np.meshgrid(np.arange(nx), np.arange(ny))
x, y = x.flatten(), y.flatten()

points = np.vstack((x,y)).T

path = Path(poly_verts)
grid = path.contains_points(points)
grid = grid.reshape((ny,nx))

print grid
30

作为对@Anil回答的一个更直接的替代方案,matplotlib有一个叫做 matplotlib.nxutils.points_inside_poly 的功能,可以用来快速处理任意形状的多边形。例如:

import numpy as np
from matplotlib.nxutils import points_inside_poly

nx, ny = 10, 10
poly_verts = [(1,1), (5,1), (5,9),(3,2),(1,1)]

# Create vertex coordinates for each grid cell...
# (<0,0> is at the top left of the grid in this system)
x, y = np.meshgrid(np.arange(nx), np.arange(ny))
x, y = x.flatten(), y.flatten()

points = np.vstack((x,y)).T

grid = points_inside_poly(points, poly_verts)
grid = grid.reshape((ny,nx))

print grid

这个操作会得到一个布尔类型的numpy数组:

[[False False False False False False False False False False]
 [False  True  True  True  True False False False False False]
 [False False False  True  True False False False False False]
 [False False False False  True False False False False False]
 [False False False False  True False False False False False]
 [False False False False  True False False False False False]
 [False False False False False False False False False False]
 [False False False False False False False False False False]
 [False False False False False False False False False False]
 [False False False False False False False False False False]]

你应该可以很顺利地将 grid 传递给任何 scipy.ndimage.morphology 的函数。

98

答案其实很简单:

import numpy
from PIL import Image, ImageDraw

# polygon = [(x1,y1),(x2,y2),...] or [x1,y1,x2,y2,...]
# width = ?
# height = ?

img = Image.new('L', (width, height), 0)
ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1)
mask = numpy.array(img)

撰写回答