第一步
假设您希望在一个输入数组中获得窗口大小为3 x 3
,并仅考虑北、西、东、南四个相邻元素的滑动窗口平均值。
对于这种情况,可以使用signal.convolve2d
函数和适当的卷积核。最后,您需要将这些总和除以卷积核中的1的数量,即kernel.sum()
,因为只有这些元素对总和产生了贡献。以下是实现方法-
import numpy as np
from scipy import signal
a = [[1,2,3],[3,4,5],[5,6,7],[4,8,9]]
arr = np.asarray(a,float)
kernel = np.array([[0,1,0],
[1,0,1],
[0,1,0]])
out = signal.convolve2d(arr, kernel, boundary='wrap', mode='same')/kernel.sum()
第二步
这个步骤和第一步的假设相同,只是我们希望在仅有零元素的邻域中寻找平均值,并用这些平均值替换它们。
方法 #1:以下是使用手动选择卷积方法完成此操作的一种方式 -
import numpy as np
arr = np.asarray(a,float)
arr_pad = np.lib.pad(arr, (1,1), 'wrap')
R,C = np.where(arr==0)
N = arr_pad.shape[1]
offset = np.array([-N, -1, 1, N])
idx = np.ravel_multi_index((R+1,C+1),arr_pad.shape)[:,None] + offset
arr_out = arr.copy()
arr_out[R,C] = arr_pad.ravel()[idx].sum(1)/4
样例输入,输出 -
In [587]: arr
Out[587]:
array([[ 4., 0., 3., 3., 3., 1., 3.],
[ 2., 4., 0., 0., 4., 2., 1.],
[ 0., 1., 1., 0., 1., 4., 3.],
[ 0., 3., 0., 2., 3., 0., 1.]])
In [588]: arr_out
Out[588]:
array([[ 4. , 3.5 , 3. , 3. , 3. , 1. , 3. ],
[ 2. , 4. , 2. , 1.75, 4. , 2. , 1. ],
[ 1.5 , 1. , 1. , 1. , 1. , 4. , 3. ],
[ 2. , 3. , 2.25, 2. , 3. , 2.25, 1. ]])
为了处理边界条件,填充有其他选项。请查看numpy.pad
以获取更多信息。
方法 #2:这是之前在Shot #1
中列出的基于卷积的方法的修改版。这与之前的方法相同,只是在最后,我们选择性地用卷积输出替换零元素。下面是代码 -
import numpy as np
from scipy import signal
a = [[1,2,3],[3,4,5],[5,6,7],[4,8,9]]
arr = np.asarray(a,float)
kernel = np.array([[0,1,0],
[1,0,1],
[0,1,0]])
conv_out = signal.convolve2d(arr, kernel, boundary='wrap', mode='same')/kernel.sum()
arr_out = arr.copy()
mask = arr==0
arr_out[mask] = conv_out[mask]
备注:如果输入数组中零元素较少,则首选方法1
,否则请使用方法2
。
i
和j
作为输入,然后我们会计算出这些坐标周围邻近区域的平均值? - Divakar