给出一个2d矩阵,例如:
A = array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
如何在给定元素周围选择NxN
窗口,以便如果窗口超出原始数组,窗口将填充任意(例如均值)值?
示例:
neighbors(A, x=0, y=0, N=3)
会产生
array([[ 2.5, 2.5, 2.5],
[ 2.5, 0, 1],
[ 2.5, 4, 5]])
答案 0 :(得分:6)
你可以pad你的阵列。填充将使用所需的边界条件扩展数组(有关所有可能选项,请参阅mode
参数):
>>> A = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> N = 5 # 5x5 windows
>>> B = np.pad(A, N//2, mode='reflect')
>>> B
array([[10, 9, 8, 9, 10, 11, 10, 9],
[ 6, 5, 4, 5, 6, 7, 6, 5],
[ 2, 1, 0, 1, 2, 3, 2, 1],
[ 6, 5, 4, 5, 6, 7, 6, 5],
[10, 9, 8, 9, 10, 11, 10, 9],
[14, 13, 12, 13, 14, 15, 14, 13],
[10, 9, 8, 9, 10, 11, 10, 9],
[ 6, 5, 4, 5, 6, 7, 6, 5]])
如您所见,原始数组位于矩阵的中心,由2行2列(N//2 = 5//2 = 2
填充,均来自lef / right和bottom / top)。填充元素反映。
对于这个新数组,您可以通过正常索引数组来访问所需的邻居窗口:
>>> x = 1; y = 1 # corresponds to number 5 in the original array
>>> B[y:y+N, x:x+N]
array([[ 5, 4, 5, 6, 7],
[ 1, 0, 1, 2, 3],
[ 5, 4, 5, 6, 7],
[ 9, 8, 9, 10, 11],
[13, 12, 13, 14, 15]])
您可以选择其他填充方法,意味着是其中一个选项。
答案 1 :(得分:2)
我认为这并不太遥远:
def neighbors(arr, x, y, N):
left = max(0, x - N)
right = min(arr.shape[0], x + N)
top = max(0, y - N)
bottom = min(arr.shape[1], y + N)
window = arr[left:right+1,top:bottom+1]
fillval = window.mean()
result = np.empty((2*N+1, 2*N+1))
result[:] = fillval
ll = N - x
tt = N - y
result[ll+left:ll+right+1,tt+top:tt+bottom+1] = window
return result
答案 2 :(得分:2)
这是np.lib.pad
和np.ix_
-
Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
Acut[np.isnan(Acut)] = np.nanmean(Acut)
示例运行 -
In [76]: A
Out[76]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
In [77]: x=1; y=0; N = 3
In [78]: Ap = np.lib.pad(A.astype(float),1, 'constant', constant_values=(np.nan,np.nan))
...: Acut = Ap[np.ix_(np.arange(N)+x,np.arange(N)+y)]
...: Acut[np.isnan(Acut)] = np.nanmean(Acut)
...:
In [79]: Acut
Out[79]:
array([[ 4.5, 0. , 1. ],
[ 4.5, 4. , 5. ],
[ 4.5, 8. , 9. ]])