【发布时间】:2015-07-07 16:09:56
【问题描述】:
设置
给定一个 2D 数组,我想创建一个 3D 数组,其中沿第三维的值(即stacked[row, col, :])是[row, col] 处原始数组的扁平邻居。我想概括这个过程来处理任意(但合理的)搜索半径。
先前的研究
这个question 看起来很有希望,但我不确定我是否可以在没有(几个)for 循环的情况下真正利用它的方法。为简洁起见,我当前的方法(搜索半径为 1)如下面的示例所示。
这个question + answer 也很接近,但我特意寻找一种纯粹使用智能索引来避免循环的解决方案。
我现在拥有的
import numpy as np
np.random.seed(0)
x = np.random.random_integers(0, 10, size=(4, 5))
print(x) # * highlights the neighbors we'll see later
[[ 5 0 3 3 7]
[ 9 *3 *5 *2 4]
[ 7 *6 *8 *8 10]
[ 1 *6 *7 *7 8]]
# padding the edges
padded = np.pad(x, mode='edge', pad_width=1) # pad_width -> search radius
print(padded)
[[ 5 5 0 3 3 7 7]
[ 5 5 0 3 3 7 7]
[ 9 9 3 5 2 4 4]
[ 7 7 6 8 8 10 10]
[ 1 1 6 7 7 8 8]
[ 1 1 6 7 7 8 8]]
然后我们可以堆叠所有的邻居。 这是我想概括的操作
blocked = np.dstack([
padded[0:-2, 0:-2], # upper left
padded[0:-2, 1:-1], # upper center
padded[0:-2, 2:], # upper right
padded[1:-1, 0:-2], # middle left...
padded[1:-1, 1:-1],
padded[1:-1, 2:],
padded[2:, 0:-2], # lower left ...
padded[2:, 1:-1],
padded[2:, 2:],
])
如果单元格看起来像这样,则访问邻居(对 reshape 的调用仅用于说明目的)
print(blocked[2, 2, :].reshape(3, 3))
[[3 5 2]
[6 8 8]
[6 7 7]]
主要问题
对于给定的搜索半径,有没有一种有效的方法来概括对np.dstack的调用?
【问题讨论】:
-
这看起来像一个滑动窗口问题,已经解决了很多次了。
-
查看 scikit image 的函数 view_as_windows 和 view_as_blocks。这里有一些关于形状和步幅摆弄细节的答案。例如。 stackoverflow.com/a/4947453/553404
-
@MrE 这些功能看起来真的很酷,我认为它们可以满足我的需求。我肯定会更多地研究skimage。出于这个问题的目的——我应该提到这一点——我想避免额外的依赖。
-
我不会担心将 scikit-image 作为依赖项,但您仍然可以调整这些函数的源代码,因为它们非常简洁 github.com/scikit-image/scikit-image/blob/master/skimage/util/…
标签: python arrays numpy vectorization