【问题标题】:NumPy 2D array: selecting indices in a circleNumPy 2D 数组:选择圆圈中的索引
【发布时间】:2018-08-26 01:43:36
【问题描述】:

对于一些矩形,我们可以非常有效地选择二维数组中的所有索引:

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

...其中(x, y) 是矩形的左上角,heightwidth 是矩形选择的高度(行数)和宽度(列数)。

现在,假设我们要在给定中心坐标(cx, cy) 和半径r 的特定圆中选择二维数组中的所有索引。是否有一个 numpy 函数可以有效地实现这一点?

目前,我正在通过一个 Python 循环手动预先计算索引,该循环将索引添加到缓冲区(列表)中。因此,这对于大型二维数组来说效率很低,因为我需要将位于某个圆圈中的每个整数排队。

# 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)]

如前所述,此过程对于较大的数组/圆非常低效。有什么加快速度的想法吗?

如果有更好的方法来索引圆,这是否也适用于“任意”2D 形状?例如,我能否以某种方式传递一个表示任意形状的点的成员资格的函数来获取数组的相应 numpy 索引?

【问题讨论】:

    标签: python arrays numpy indexing


    【解决方案1】:

    您可以定义一个包含圆圈的蒙版。下面,我已经演示了一个圆圈,但你可以在mask 赋值中编写任意函数。字段mask 的维度为arr,如果满足右侧的条件,则其值为True,否则为False。此掩码可与索引运算符结合使用,以仅分配给选定的索引,如 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()
    

    【讨论】:

    • 干得好。我在我的计算机上对其进行了计时,它比我的方法快 mask = (x[np.newaxis,:]-cx)**2 + (y[:,np.newaxis]-cy)**2 < r**2吗?为什么我们需要/使用np.arange 作为xy 作为初始值?顺便说一句:使用np.newaxis 这种方式在相加后得到一个二维数组是个不错的主意。
    • 我必须生成两个坐标xy 才能计算出一个圆。你可以使用任何函数,arange 对我来说只是一个方便的选择。
    猜你喜欢
    • 2015-04-08
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 2019-04-08
    • 2019-12-23
    • 1970-01-01
    • 2022-07-08
    • 2012-11-07
    相关资源
    最近更新 更多