由另一个数组索引的数组元素的增量

时间:2019-09-13 03:46:16

标签: python numpy-ndarray

我正在实现Circle Hough变换,所以我有一个3D Numpy数组mask = torch.from_numpy(mask) mask = mask.expand_as(img) img = img * mask ,这些数组代表可能的Xcenter,Ycenter和Radius组合。我想增加由另一个2D Numpy数组C索引的计数器。因此,例如,如果I

I

然后我想说些类似的话:

[[xc0, yc0, r0],
 ...,
 [xcN, ycN, rN]]

我希望效果是

C[I] = C[I] + 1

但是,执行的索引似乎是混乱的,引用了C[xc0, yc0, r0] = C[xc0, yc0, r0] + 1 ... C[xcN, ycN, rN] = C[xcN, ycN, rN] + 1 中的错误条目。此外,我真的很想说这样的话:

C

因为这似乎会减少索引计算量。

因此,有两个问题:

  • 如何获得“按数组索引的数组”的效果?
  • 我可以放弃使用增量运算符吗,它实际上可以节省任何时间吗?

3 个答案:

答案 0 :(得分:2)

您正在寻找的技术通常称为advancedfancy索引。花式索引的前提是,每个维度都需要可广播大小的索引。索引数组中每个位置的相应元素从要索引的数组中选择一个元素。就您而言,这意味着您需要将I划分为不同的维度。由于I当前为N x 3,因此您可以

C[tuple(I.T)] += 1

如果您可以以某种方式预置I,则可以

C[*I] += 1

到目前为止,使用就地增量是您最好的选择。如果你这样做

C[tuple(I.T)] = C[tuple(I.T)] + 1

将创建N索引元素的副本。然后,副本将增加,并正确地重新分配给源阵列。您可以想象这比仅增加适当的值要昂贵得多。

答案 1 :(得分:0)

我支持@MadPhysicist的建议。以下详细阐述了他的建议,并验证了您获得的结果是一致的。

可能的方法

# method-1
C[I[:,0], I[:,1], I[:,2]] += 1

# method-2
C[tuple(I.T)] += 1
  

详细解决方案

制作虚拟数据

I = np.vstack([
    np.random.randint(6, size=10), 
    np.random.randint(5, size=10), 
    np.random.randint(3, size=10), 
]).T
C = np.arange(90).reshape((6,5,3))
I

输出

array([[2, 3, 2],
       [1, 3, 2],
       [2, 0, 0],
       [0, 3, 0],
       [2, 0, 2],
       [2, 3, 2],
       [4, 0, 2],
       [2, 1, 2],
       [4, 1, 1],
       [1, 1, 1]])

首先,我们使用列表理解

在此,我们将C视为其索引的子集,同时从I中提取值。因此,如果我们遵循@MadPhysicist的建议,我们将知道会发生什么。

I2 = [tuple(x) for x in tuple(I)]
[C[x] for x in I2]

输出

[41, 26, 30, 9, 32, 41, 62, 35, 64, 19]

对照检查

让我们看看I2中的内容。

[(2, 3, 2),
 (1, 3, 2),
 (2, 0, 0),
 (0, 3, 0),
 (2, 0, 2),
 (2, 3, 2),
 (4, 0, 2),
 (2, 1, 2),
 (4, 1, 1),
 (1, 1, 1)]

因此,这表明我们有切实的东西。

测试其他方法

方法1

C[I[:,0], I[:,1], I[:,2]]

方法2

C[tuple(I.T)]

输出

方法1和2都产生与以前相同的结果。

array([41, 26, 30,  9, 32, 41, 62, 35, 64, 19])

好的。因此,索引问题结束了。

现在,我们解决这个问题中提出的问题。使用下面的方法1或方法2。方法2更简洁(如@MadPhysicist建议)。

# method-1
C[I[:,0], I[:,1], I[:,2]] += 1

# method-2
C[tuple(I.T)] += 1

快速测试

为安全起见,这里首先进行快速测试(首先不更改C)。

B = C.copy()
B[tuple(I.T)] += 1
B[tuple(I.T)]

输出

array([42, 27, 31, 10, 33, 42, 63, 36, 65, 20])
  

所以,它有效!

答案 2 :(得分:-1)

您可以执行以下操作:

In [3]: c = np.array([[1, 2, 3], [2, 3, 4], [3, 4, 5]])                                       

In [4]: c                                                                                     
Out[4]: 
array([[1, 2, 3],
       [2, 3, 4],
       [3, 4, 5]])

In [5]: i = [0, 2]                                                                            

In [6]: c[i]                                                                                  
Out[6]: 
array([[1, 2, 3],
       [3, 4, 5]])

In [7]: c[i] + 1                                                                              
Out[7]: 
array([[2, 3, 4],
       [4, 5, 6]])
  1. 您可以简单地将其设为c[i],其中i是索引。 (以上[5]。)
  2. 您可以简单地让numpy处理这些东西。通过广播标量来处理递增1或向矩阵中添加一些标量。至于是否更快,我不知道。您可以在此处了解更多信息:https://docs.scipy.org/doc/numpy/user/basics.broadcasting.html

希望有帮助。