gpt4 book ai didi

python - numpy 中的矢量化二维移动窗口,包括边缘

转载 作者:太空狗 更新时间:2023-10-30 00:38:11 28 4
gpt4 key购买 nike

我意识到我的问题与 Vectorized moving window on 2D array in numpy 非常相似,但那里的答案并不能完全满足我的需求。

是否可以制作包含所谓边缘效应的矢量化二维移动窗口(滚动窗口)?执行此操作的最有效方法是什么?

也就是说,我想在我的网格上滑动移动窗口的中心,这样中心就可以移动到网格中的每个单元格上。当沿着网格的边缘移动时,此操作将仅返回与网格重叠的窗口部分。如果窗口完全在网格内,则返回整个窗口。例如,如果我有网格:

array([[1,2,3,4],
[2,3,4,5],
[3,4,5,6],
[4,5,6,7]])

…我想使用以该点为中心的 3x3 窗口对该网格中的每个点进行采样,该操作应返回一系列数组,或者理想情况下,返回原始 View 中的一系列 View 数组,如下:

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

array([[1,2], array([[1,2,3], array([[2,3,4], array([[3,4],
[2,3], [2,3,4], [3,4,5], [4,5],
[3,4]]) [3,4,5]]) [4,5,6]]) [5,6]])

array([[2,3], array([[2,3,4], array([[3,4,5], array([[4,5],
[3,4], [3,4,5], [4,5,6], [5,6],
[4,5]]) [4,5,6]]) [5,6,7]]) [6,7]])

array([[3,4], array([[3,4,5], array([[4,5,6], array([[5,6],
[4,5]]) [4,5,6]]) [5,6,7]]) [6,7]])

因为我需要多次执行此操作,所以速度很重要,理想的解决方案是矢量化操作。

最佳答案

您可以定义一个生成生成器的函数并使用它。该窗口将是您想要的形状的底部除以 2,技巧就是在您沿着行和列移动时沿着该窗口索引数组。

def window(arr, shape=(3, 3)):
# Find row and column window sizes
r_win = np.floor(shape[0] / 2).astype(int)
c_win = np.floor(shape[1] / 2).astype(int)
x, y = arr.shape
for i in range(x):
xmin = max(0, i - r_win)
xmax = min(x, i + r_win + 1)
for j in range(y):
ymin = max(0, j - c_win)
ymax = min(y, j + c_win + 1)
yield arr[xmin:xmax, ymin:ymax]

你可以像这样使用这个函数:

arr = np.array([[1,2,3,4],
[2,3,4,5],
[3,4,5,6],
[4,5,6,7]])
gen = window(arr)
next(gen)
array([[1, 2],
[2, 3]])

通过生成器生成示例中的所有窗口。

它不是矢量化的,但我不确定是否存在返回不同大小数组的现有矢量化函数。正如@PaulPanzer 指出的那样,您可以将数组填充到您需要的大小并使用 np.lib.stride_tricks.as_strided生成切片的 View 。像这样:

def rolling_window(a, shape):
s = (a.shape[0] - shape[0] + 1,) + (a.shape[1] - shape[1] + 1,) + shape
strides = a.strides + a.strides
return np.lib.stride_tricks.as_strided(a, shape=s, strides=strides)

def window2(arr, shape=(3, 3)):
r_extra = np.floor(shape[0] / 2).astype(int)
c_extra = np.floor(shape[1] / 2).astype(int)
out = np.empty((arr.shape[0] + 2 * r_extra, arr.shape[1] + 2 * c_extra))
out[:] = np.nan
out[r_extra:-r_extra, c_extra:-c_extra] = arr
view = rolling_window(out, shape)
return view

window2(arr, (3,3))
array([[[[ nan, nan, nan],
[ nan, 1., 2.],
[ nan, 2., 3.]],

[[ nan, nan, nan],
[ 1., 2., 3.],
[ 2., 3., 4.]],

[[ nan, nan, nan],
[ 2., 3., 4.],
[ 3., 4., 5.]],

[[ nan, nan, nan],
[ 3., 4., nan],
[ 4., 5., nan]]],


[[[ nan, 1., 2.],
[ nan, 2., 3.],
[ nan, 3., 4.]],

[[ 1., 2., 3.],
[ 2., 3., 4.],
[ 3., 4., 5.]],

[[ 2., 3., 4.],
[ 3., 4., 5.],
[ 4., 5., 6.]],

[[ 3., 4., nan],
[ 4., 5., nan],
[ 5., 6., nan]]],


[[[ nan, 2., 3.],
[ nan, 3., 4.],
[ nan, 4., 5.]],

[[ 2., 3., 4.],
[ 3., 4., 5.],
[ 4., 5., 6.]],

[[ 3., 4., 5.],
[ 4., 5., 6.],
[ 5., 6., 7.]],

[[ 4., 5., nan],
[ 5., 6., nan],
[ 6., 7., nan]]],


[[[ nan, 3., 4.],
[ nan, 4., 5.],
[ nan, nan, nan]],

[[ 3., 4., 5.],
[ 4., 5., 6.],
[ nan, nan, nan]],

[[ 4., 5., 6.],
[ 5., 6., 7.],
[ nan, nan, nan]],

[[ 5., 6., nan],
[ 6., 7., nan],
[ nan, nan, nan]]]])

此版本使用 np.nan 填充边缘以避免与数组中的任何其他值混淆。给定的数组比 window 函数快大约 3 倍,但我不确定填充输出将如何影响你想在下游做的任何事情。

关于python - numpy 中的矢量化二维移动窗口,包括边缘,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48215914/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com