在 np.array 上实现无重叠的 2D 滑动窗口(平铺、均值池化)

问题描述 投票:0回答:3

我正在尝试实现立方形状 (k,k) 的 2D 滑动窗口,以便我可以迭代帧 (n,m,3) 并计算每个窗口中像素值的平均值。 我希望每次迭代时,窗口都会显示下一张幻灯片,而没有任何重叠的值; 即给定这个矩阵:

[
  [1, 2, 3, 4],
  [5, 6, 7 ,8],
  [9, 10, 11, 12],
  [13, 14, 15, 16]
 ]

对于 k = 2 我会得到如下的东西:

 [
  [1, 2],
  [5, 6]
 ]

第二个窗口的值如下:

 [
  [3, 4],
  [7, 8]
 ]

等等。

我尝试过使用 numpy.lib.stride_tricks.as_strided。 但没有任何成功。

使用 numpy 或任何其他高效的库也很重要,因为使用 python for 循环实现此代码对于该操作来说太昂贵了。

python numpy image-processing multidimensional-array signal-processing
3个回答
1
投票

忽略第三个维度,既然它似乎没有进入问题,那么怎么样:

# Generate array of size (m*k, n*k)
# my m, n are your m, n divided by k
m, n = 2, 4
k = 3
x = np.arange(m*n*k*k).reshape((m*k, n*k))
# array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11],
#        [12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23],
#        [24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35],
#        [36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47],
#        [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
#        [60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71]])

# Calculate means of each block
y = x.reshape((m, k, n, k))
z = np.moveaxis(y, -3, -2)  # now shape is (m, n, k, k) 
np.mean(z, axis=(-2, -1))  # take mean over last two axes
# or just np.mean(y, axis=(-3, -1)) 
# array([[13., 16., 19., 22.],
#        [49., 52., 55., 58.]])

要保留第三维并分别对每个颜色通道进行计算,只需在开始时将其移开(例如,移至轴

0
),然后在末尾将其移回。

如果行数和/或列数不能被

k
整除,您可以使用数据中未出现的一些哨兵值(例如
nan
)填充数组,直到行数/列数可整除由
k
。然后,以某种方式采用忽略标记值的方法(例如
nanmean
)。 (或者,拆分剩余的行/列,单独处理它们,然后合并结果。)

scipy.ndimage
或 scikit-image 中可能有一些东西可以在一行中完成此操作。我尝试过
zoom
,但没有找到能够给出所需结果的神奇设置组合。


0
投票
In [374]: win = np.lib.stride_tricks.sliding_window_view(arr,(2,2))

In [375]: win.shape
Out[375]: (3, 3, 2, 2)

采用每隔一个、不重叠的窗口:

In [376]: win[::2,::2]
Out[376]: 
array([[[[ 1,  2],
         [ 5,  6]],

        [[ 3,  4],
         [ 7,  8]]],


       [[[ 9, 10],
         [13, 14]],

        [[11, 12],
         [15, 16]]]])

重塑替代方案:

In [378]: arr.reshape(2,2,2,2).transpose(0,2,1,3)
Out[378]: 
array([[[[ 1,  2],
         [ 5,  6]],

        [[ 3,  4],
         [ 7,  8]]],


       [[[ 9, 10],
         [13, 14]],

        [[11, 12],
         [15, 16]]]])

-1
投票

这是一个张量流解决方案:

from tensorflow.keras.layers import AveragePooling2D
x = np.array([[1, 2, 3, 4],[5, 6, 7 ,8],[9, 10, 11, 12],[13, 14, 15, 16]])
y = x.reshape(1,*x.shape, 1).astype(float) # you need 4d

AveragePooling2D(2, 2)(y).numpy().squeeze()
array([[ 3.5,  5.5],
       [11.5, 13.5]], dtype=float32)

AveragePooling2D(pool_size = (2,2), strides = (1,1))(y).numpy().squeeze() 
array([[ 3.5,  4.5,  5.5],
       [ 7.5,  8.5,  9.5],
       [11.5, 12.5, 13.5]], dtype=float32)

© www.soinside.com 2019 - 2024. All rights reserved.