如何从位于数组顶部的多边形内的NumPy 2-D数组中提取值?

问题描述:

我的目标如下:给定一个二维数组和一个可以放置在数组顶部的多边形,我想要拉出多边形内的值(包含的边界)并求和这些值。如何从位于数组顶部的多边形内的NumPy 2-D数组中提取值?

假设我有一个2-d阵列是这样的:

1 6 8 4 2 3 
5 4 1 3 7 9 
1 0 2 3 4 8 
6 7 0 5 7 4 
0 1 2 5 4 2 

并假设我有以下顶点的多边形:

(1, 2) 
(2, 3) 
(3, 3) 
(4, 2) 
(4, 1) 
(3, 1) 
(2, 1) 
(1, 2) 

铺设在阵列的顶部的多边形会导致在下面:

_ _ _ _ _ _ 
_ _ 1 _ _ _ 
_ 0 2 3 _ _ 
_ 7 0 5 _ _ 
_ 1 2 _ _ _ 

最后,我想总结这些值。所以最终的输出将是21.

什么是最有效的方式来做到这一点?我已经看到matplotlib.path和Shapely的引用,但是我没有找到任何能够满足我需要的东西的地方,除非我只是错过了某些东西(这当然是可行的)。看起来这个功能应该被构建到NumPy中,但是如果是的话,我还没有遇到过。

为什么我需要这个:我有一个代表世界人口的ASCII网格,我有政治边界。我想覆盖人口网格上的政治边界,以确定该地点的总人口数量。

+0

我会建议将numpy数组转换成图像,然后使用图像处理工具(OpenCV?) – DyZ

步骤参与 -

  • 创建相同的形状作为图像阵列的一个布尔值数组。

  • 使用给定的轮廓点填充轮廓。

  • 通过填充轮廓点创建的孔创建多边形斑点。

  • 布尔索引到带有填充掩码的图像数组中并获得总和。

实现 -

from scipy.ndimage.morphology import binary_fill_holes as imfill 

mask = np.zeros(img.shape,dtype=bool) 
mask[idx[:,0], idx[:,1]] = 1 
out = img[imfill(mask)].sum() 

样品运行 -

1)输入图像和多边形轮廓的积分:建议

In [107]: img 
Out[107]: 
array([[1, 6, 8, 4, 2, 3], 
     [5, 4, 1, 3, 7, 9], 
     [1, 0, 2, 3, 4, 8], 
     [6, 7, 0, 5, 7, 4], 
     [0, 1, 2, 5, 4, 2]]) 

In [108]: idx 
Out[108]: 
array([[1, 2], 
     [2, 3], 
     [3, 3], 
     [4, 2], 
     [4, 1], 
     [3, 1], 
     [2, 1], 
     [1, 2]]) 

2)码:

In [109]: mask = np.zeros(img.shape,dtype=bool) 
    ...: mask[idx[:,0], idx[:,1]] = 1 
    ...: out = img[imfill(mask)].sum() 
    ...: 

3)分析结果:

In [134]: imfill(mask) # Polygon mask 
Out[134]: 
array([[False, False, False, False, False, False], 
     [False, False, True, False, False, False], 
     [False, True, True, True, False, False], 
     [False, True, True, True, False, False], 
     [False, True, True, False, False, False]], dtype=bool) 

In [135]: img[imfill(mask)] 
Out[135]: array([1, 0, 2, 3, 7, 0, 5, 1, 2]) 

In [136]: img[imfill(mask)].sum() 
Out[136]: 21 
+0

美丽!这正如我所希望的那样简单。谢谢! – Geoff

+1

为什么不简单地'img [idx [:,0],idx [:,1]]。sum()'? –

+2

@ P-robot猜测在之前的样品运行中并不清楚。我们还需要多边形内的点,而不仅仅是由'idx'表示的多边形轮廓上的点。所以,我们需要所有的工作来填充blob并调用'ndimage'的帮助:) – Divakar

我不知道这是最有效的(最有可能没有),但它的矢量化和它的作品。 a是'图片',b是多边形。

i, k = np.indices(a.shape) 
z = i+k*1j 
p = b[:,0]+b[:,1]*1j 
m = np.unwrap(np.angle(z[..., None]-p), axis=-1) 
m = ~np.isclose (m[...,-1], m[...,0]) | np.any(np.isclose(z[..., None], p), axis=-1) 
res = np.sum(a[m]) 
# 21 -> res