块状广播数组到较小的数组,每行的确切位置

时间:2019-07-04 06:19:50

标签: python numpy

考虑示例矩阵数组:

[[0 1 2 1 0]
 [1 1 2 1 0]
 [0 1 0 0 0]
 [1 2 1 0 0]
 [1 2 2 3 2]]

我需要做什么:

  1. 在每一行中找到最大值
  2. 从每行中选择较小的最大值周围(本例中为3个值)
  3. 将最大值的周围粘贴到新的数组中(更窄)

对于上面的示例,结果是:

[[ 1.  2.  1.]
 [ 1.  2.  1.]
 [ 0.  1.  0.]
 [ 1.  2.  1.]
 [ 2.  3.  2.]]

我当前的工作代码:

import numpy as np

A = np.array([
    [0, 1, 2, 1, 0],
    [1, 1, 2, 1, 0],
    [0, 1, 0, 0, 0],
    [1, 2, 1, 0, 0],
    [1, 2, 2, 3, 2],
])

b = A.argmax(axis=1)

C = np.zeros((len(A), 3))
for idx, loc, row in zip(range(len(A)), b, A):
    print(idx, loc, row)
    C[idx] = row[loc-1:loc+2]

print(C)

我的问题:

如何摆脱for循环并将其替换为一些更便宜的numpy操作?

注意:

此算法用于矫正具有数千行的视频流帧中的折线。

2 个答案:

答案 0 :(得分:1)

方法1

我们可以基于设置滑动窗口,然后为具有b偏移索引的索引建立索引,以得到所需的输出,从而获得矢量化解决方案。我们可以利用基于np.lib.stride_tricks.as_stridedscikit-image's view_as_windows来获取滑动窗口。 More info on use of as_strided based view_as_windows

实施方式为-

     .mainBackground {
            background-color: #ece8e8;
            width: 100%;
        }

    <div class="mainBackground">
        hello
    </div>

作为基于视图的方法,它的优点是内存效率高,因此也具有良好的性能。

方法2

或者,通过创建所有具有外部加法的索引的单线将是-

{{1}}

答案 1 :(得分:1)

这可以通过对所有所需索引进行制作和排列来实现,但是以某种方式直接在A上使用它会生成3D数组,因此随后的索引编制……可能不是最佳方法,但绝对是另一种方法!

import numpy as np

A = np.array([
    [0, 1, 2, 1, 0],
    [1, 1, 2, 1, 0],
    [0, 1, 0, 0, 0],
    [1, 2, 1, 0, 0],
    [1, 2, 2, 3, 2],
])

b = A.argmax(axis = 1).reshape(-1, 1)
index = b + np.arange(-1,2,1).reshape(1, -1)
A[:,index][np.arange(b.size),np.arange(b.size)]