我有一个numpy数组(A)和一个权重矩阵(比如m,这是一种过滤器)。我想在A的每个元素上应用此过滤器,并为A的每个元素获取一个邻居数组乘以m。
例如,如果m是3x3内核,那么我们得到:
对于每个(i,j),A [i,j] - >数组([A [i-1,j-1] * m [0,0],A [i-1,j] * m [0,1],...,A [i + 1,j + 1 ] * M [2,2]])
因此,输出将比A更多。 对于边界情况,我需要考虑部分过滤器(相当于用零填充)。有效的方法吗?
答案 0 :(得分:2)
这是一种使用skimage's view_as_windows
的方法,它为我们提供了所需内核形状的滑动窗口 -
from skimage.util import view_as_windows as viewW
# Pad with one layer of zeros around input array
a1 = np.lib.pad(a, (1,1), 'constant', constant_values=0)
# Create 3x3 sliding windows for each elem and multiply with m.
# Reshape each window as a 9 elem list as per requirement.
out = (viewW(a1,[3,3])*m).reshape(a.shape + (9,))
示例运行
1]输入数组 -
In [64]: a
Out[64]:
array([[75, 46, 74, 72, 96],
[44, 72, 41, 81, 50],
[16, 70, 22, 19, 49],
[87, 74, 78, 66, 49]])
2]输入数组填充 -
In [65]: a1
Out[65]:
array([[ 0, 0, 0, 0, 0, 0, 0],
[ 0, 75, 46, 74, 72, 96, 0],
[ 0, 44, 72, 41, 81, 50, 0],
[ 0, 16, 70, 22, 19, 49, 0],
[ 0, 87, 74, 78, 66, 49, 0],
[ 0, 0, 0, 0, 0, 0, 0]])
3] 3D输出数组 -
In [66]: out
Out[66]:
array([[[ 0, 0, 0, 0, 450, 276, 0, 220, 504],
[ 0, 0, 0, 450, 276, 444, 352, 360, 287],
[ 0, 0, 0, 276, 444, 432, 576, 205, 567],
[ 0, 0, 0, 444, 432, 576, 328, 405, 350],
[ 0, 0, 0, 432, 576, 0, 648, 250, 0]],
[[ 0, 300, 276, 0, 264, 432, 0, 80, 490],
[375, 184, 444, 264, 432, 246, 128, 350, 154],
[230, 296, 432, 432, 246, 486, 560, 110, 133],
[370, 288, 576, 246, 486, 300, 176, 95, 343],
[360, 384, 0, 486, 300, 0, 152, 245, 0]],
[[ 0, 176, 432, 0, 96, 420, 0, 435, 518],
[220, 288, 246, 96, 420, 132, 696, 370, 546],
[360, 164, 486, 420, 132, 114, 592, 390, 462],
[205, 324, 300, 132, 114, 294, 624, 330, 343],
[405, 200, 0, 114, 294, 0, 528, 245, 0]],
[[ 0, 64, 420, 0, 522, 444, 0, 0, 0],
[ 80, 280, 132, 522, 444, 468, 0, 0, 0],
[350, 88, 114, 444, 468, 396, 0, 0, 0],
[110, 76, 294, 468, 396, 294, 0, 0, 0],
[ 95, 196, 0, 396, 294, 0, 0, 0, 0]]])
4]让我们验证结果。未填充区域上的第一个滑动窗口为a[:3,:3]
。让我们将其与m
相乘。乘法后,它应与out[1,1,:]
-
In [67]: a[:3,:3]*m
Out[67]:
array([[375, 184, 444],
[264, 432, 246],
[128, 350, 154]])
In [68]: out[1,1,:]
Out[68]: array([375, 184, 444, 264, 432, 246, 128, 350, 154])
值得一提的是,3D
滑动窗口数组只是对数组的视图,因此在涉及那些的进一步操作时非常有效 -
In [75]: np.may_share_memory(a1,viewW(a1,[3,3]))
Out[75]: True
答案 1 :(得分:1)
你所描述的是卷积,它通常用于图像处理(wiki:https://en.wikipedia.org/wiki/Kernel_(image_processing); http://www.songho.ca/dsp/convolution/convolution2d_example.html)。
scipy.signal.convolve2d(arr, filter)
可以达到预期的效果。如上面的链接所述,卷积将滤波器或内核矩阵旋转180度,因此您可以利用numpy.rot90(array)
来实现所需的效果。
方法签名可能最终看起来像:
scipy.signal.convolve2d(arr, np.rot90(np.rot90(filter)))