简体   繁体   English

NumPy 二维数组:在一个圆圈中选择索引

[英]NumPy 2D array: selecting indices in a circle

For some rectangular we can select all indices in a 2D array very efficiently:对于一些矩形,我们可以非常有效地 select 二维数组中的所有索引:

arr[y:y+height, x:x+width]

...where (x, y) is the upper-left corner of the rectangle and height and width the height (number of rows) and width (number of columns) of the rectangular selection. ...其中(x, y)是矩形的左上角, heightwidth是矩形选区的高度(行数)和宽度(列数)。

Now, let's say we want to select all indices in a 2D array located in a certain circle given center coordinates (cx, cy) and radius r .现在,假设我们想要 select 位于给定圆心坐标(cx, cy)和半径r的某个圆中的二维数组中的所有索引。 Is there a numpy function to achieve this efficiently?是否有 numpy function 可以有效地实现这一目标?

Currently I am pre-computing the indices manually by having a Python loop that adds indices into a buffer (list).目前,我正在通过 Python 循环手动预计算索引,该循环将索引添加到缓冲区(列表)中。 Thus, this is pretty inefficent for large 2D arrays, since I need to queue up every integer lying in some circle.因此,这对于大型 2D arrays 来说非常低效,因为我需要对位于某个圆圈中的每个 integer 进行排队。

# buffer for x & y indices
indices_x = list()
indices_y = list()

# lower and upper index range
x_lower, x_upper = int(max(cx-r, 0)), int(min(cx+r, arr.shape[1]-1))
y_lower, y_upper = int(max(cy-r, 0)), int(min(cy+r, arr.shape[0]-1))
range_x = range(x_lower, x_upper)
range_y = range(y_lower, y_upper)

# loop over all indices
for y, x in product(range_y, range_x):
    # check if point lies within radius r
    if (x-cx)**2 + (y-cy)**2 < r**2:
        indices_y.append(y)
        indices_x.append(x)

# circle indexing
arr[(indices_y, indices_x)]

As mentioned, this procedure gets quite inefficient for larger arrays / circles.如前所述,对于较大的 arrays / 圆,此过程变得非常低效。 Any ideas for speeding things up?有什么加快速度的想法吗?

If there is a better way to index a circle, does this also apply for "arbitrary" 2D shapes?如果有更好的方法来索引圆,这是否也适用于“任意”二维形状? For example, could I somehow pass a function that expresses membership of points for an arbitrary shape to get the corresponding numpy indices of an array?例如,我能否以某种方式传递一个 function 来表示任意形状的点的成员资格,以获得数组的相应 numpy 索引?

You could define a mask that contains the circle.您可以定义一个包含圆圈的蒙版。 Below, I have demonstrated it for a circle, but you could write any arbitrary function in the mask assignment.下面,我用一个圆演示了它,但是您可以在mask分配中编写任意函数。 The field mask has the dimensions of arr and has the value True if the condition on the righthand side is satisfied, and False otherwise.字段mask的维度为arr ,如果满足右侧的条件,则值为True ,否则为False This mask can be used in combination with the indexing operator to assign to only a selection of indices, as the line arr[mask] = 123. demonstrates.此掩码可与索引运算符结合使用,以仅分配给一组索引,如行arr[mask] = 123.所示。

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 32)
y = np.arange(0, 32)
arr = np.zeros((y.size, x.size))

cx = 12.
cy = 16.
r = 5.

# The two lines below could be merged, but I stored the mask
# for code clarity.
mask = (x[np.newaxis,:]-cx)**2 + (y[:,np.newaxis]-cy)**2 < r**2
arr[mask] = 123.

# This plot shows that only within the circle the value is set to 123.
plt.figure(figsize=(6, 6))
plt.pcolormesh(x, y, arr)
plt.colorbar()
plt.show()

Thank you Chiel for your answer, but I couldn't see radius 5 in the output.(diameter is 9 in output and not 10)谢谢 Chiel 的回答,但我在 output 中看不到半径 5。(output 中的直径为 9 而不是 10)

One can reduce.5 from cx and cy to produce diameter 10可以从cx和 cy减少 5 以产生直径 10

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 32)
y = np.arange(0, 32)
arr = np.zeros((y.size, x.size))

cx = 12.-.5
cy = 16.-.5
r = 5.

# The two lines below could be merged, but I stored the mask
# for code clarity.
mask = (x[np.newaxis,:]-cx)**2 + (y[:,np.newaxis]-cy)**2 < r**2
arr[mask] = 123.

# This plot shows that only within the circle the value is set to 123.
plt.figure(figsize=(6, 6))
plt.pcolormesh(x, y, arr)
plt.colorbar()
plt.show()

区别

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

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