简体   繁体   English

填充numpy数组中的相邻元素

[英]Fill neighboring elements in numpy array

Not sure whats the best way to title this question, but basically I would like to fill an existing numpy array with a value, based on the location provided and a specified distance. 不知道什么是标题这个问题的最好方法,但基本上我想根据提供的位置和指定的距离用现有的numpy数组填充一个值。 Assuming going diagonally is not valid. 假设对角线无效。

For example, lets say we have an array with just 0s. 例如,假设我们有一个只有0的数组。

[[0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 0]]

If I want (2,2) as the location with distance 1, it would fill the matrix with value 1, in the location that has distance one from the location provided, including itself. 如果我想要(2,2)作为距离1的位置,它将填充矩阵的值为1,位于距离提供的位置1的位置,包括其自身。 Thus the matrix would look like: 因此矩阵看起来像:

[[0 0 0 0 0]
 [0 0 1 0 0]
 [0 1 1 1 0]
 [0 0 1 0 0]
 [0 0 0 0 0]]

And if I provided a distance of 2, it would look like: 如果我提供的距离为2,它看起来像:

[[0 0 1 0 0]
 [0 1 1 1 0]
 [1 1 1 1 1]
 [0 1 1 1 0]
 [0 0 1 0 0]]

Basically everything within a distance of 2 from the location will be filled with the value 1. Assuming diagonal movement is not valid. 基本上距离该位置2的距离内的所有内容都将填充值1.假设对角线移动无效。

I also would like to support wrapping, where if the neighboring elements are out of bounds, it will wrap around. 我也想支持包装,如果相邻的元素超出范围,它将环绕。

For example, if the location provided is (4,4) with distance 1, the matrix should look like so: 例如,如果提供的位置是(4,4)距离为1,则矩阵应如下所示:

[[0 0 0 0 1]
 [0 0 0 0 0]
 [0 0 0 0 0]
 [0 0 0 0 1]
 [1 0 0 1 1]]

I tried using np.ogrid along with a mask of where the 1's will be true but cant seem to get it working. 我尝试使用np.ogrid以及1将是真实的掩码,但似乎无法使其正常工作。

What you are trying to do is essentially binary dilation , but the wrapping poses a problem. 你要做的实际上是二元扩张 ,但包裹带来了问题。 Luckily, scipy 's grey dilation function has the wrap mode which we can leverage: 幸运的是, scipy灰色扩张功能具有我们可以利用的wrap模式:

from scipy.ndimage.morphology import grey_dilation, generate_binary_structure, iterate_structure

st = generate_binary_structure(2,1)

# st essentially defines "neighbours", 
# and you can expand n times this using iterate_structure(st, n):

# >>> st
# array([[False,  True, False],
#        [ True,  True,  True],
#        [False,  True, False]])

# >>> iterate_structure(st,2)
# array([[False, False,  True, False, False],
#        [False,  True,  True,  True, False],
#        [ True,  True,  True,  True,  True],
#        [False,  True,  True,  True, False],
#        [False, False,  True, False, False]])


a = np.zeros((5,5))
a[4,4] = 1
dist = 1

dilated = grey_dilation(a, footprint = iterate_structure(st,dist), mode='wrap')

And as a function that creates your array for you: 并且作为为您创建阵列的函数:

from scipy.ndimage.morphology import grey_dilation, generate_binary_structure, iterate_structure

def create(size, dist, loc):
    a = np.zeros((size,size), dtype=int)
    a[loc] = 1
    st = generate_binary_structure(2,1)
    return grey_dilation(a, footprint = iterate_structure(st,dist), mode='wrap')

Examples : To reproduce your desired inputs and outputs: 示例 :重现所需的输入和输出:

>>> create(5, 1, (2,2))
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 1, 1, 1, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0]])

>>> create(5, 2, (2,2))
array([[0, 0, 1, 0, 0],
       [0, 1, 1, 1, 0],
       [1, 1, 1, 1, 1],
       [0, 1, 1, 1, 0],
       [0, 0, 1, 0, 0]])

>>> create(5, 1, (4,4))
array([[0, 0, 0, 0, 1],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1],
       [1, 0, 0, 1, 1]])
def create(size, dist, loc):
    a = np.zeros((size, size))
    for i in range(-dist, dist + 1):
        for j in range(-dist + abs(i), dist - abs(i) + 1):
            i_ = (i + loc[0]) % size
            j_ = (j + loc[1]) % size
            a[i_, j_] = 1
    return a

create(5, 1, (4, 4))

returns 回报

array([[0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 1.],
       [1., 0., 0., 1., 1.]])

This may not be the most efficient solution but you could try iterating through all the elements in the array, check if their distance to the location provided is what you want it to be and if it is, replace that element's value with the value specified. 这可能不是最有效的解决方案,但您可以尝试遍历数组中的所有元素,检查它们到所提供位置的距离是否是您想要的,如果是,请将该元素的值替换为指定的值。 Basic code structure: 基本代码结构:

# declar my_arr
value = 1
distance = 2
centre_point = (4,4)
for row_index in range(len(my_arr)):
    for col_index in range(len(my_arr[row_index])):
        if distanceToPoint(row_index,col_index,centre_point) <= distance:
            my_arr[row_index][col_index] = value

The distanceToPoint function would be something like this: distanceToPoint函数将是这样的:

def distanceToPoint(x,y,point):
   px,py = point
   dx,dy = px-x,py-y
   if x==px:
       return py-y
   if y==py:
       return px-x
   if abs(dx)==abs(dy):
       return dx
   else:
       return 1000000 #an arbitrarily large amount which should be bigger than distance

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM