# arrays - numpy卷积运算 - 使用numpy`as_strided`函数创建任意维度的补丁,平铺,滚动或滑动窗口

## scipy ndimage convolve用法 (1)

@Divakar在 here 为1-d输入创建了一个通用的 `numpy` 函数，但是更高维度的输入需要更多的关注。 我 在3d输入法上 制作了一个裸骨 2D窗口 ，但它不是很可扩展。

``````def window_nd(a, window, steps = None, axis = None, outlist = False):
"""
Create a windowed view over `n`-dimensional input that uses an
`m`-dimensional window, with `m <= n`

Parameters
-------------
a : Array-like
The array to create the view on

window : tuple or int
If int, the size of the window in `axis`, or in all dimensions if
`axis == None`

If tuple, the shape of the desired window.  `window.size` must be:
equal to `len(axis)` if `axis != None`, else
equal to `len(a.shape)`, or
1

steps : tuple, int or None
The offset between consecutive windows in desired dimension
If None, offset is one in all dimensions
If int, the offset for all windows over `axis`
If tuple, the steps along each `axis`.
`len(steps)` must me equal to `len(axis)`

axis : tuple, int or None
The axes over which to apply the window
If None, apply over all dimensions
if tuple or int, the dimensions over which to apply the window

outlist : boolean
If output should be as list of windows.
If False, it will be an array with
`a.nidim + 1 <= a_view.ndim <= a.ndim *2`.
If True, output is a list of arrays with `a_view[0].ndim = a.ndim`
Warning: this is a memory-intensive copy and not a view

Returns
-------

a_view : ndarray
A windowed view on the input array `a`, or copied list of windows

"""
ashp = np.array(a.shape)

if axis != None:
axs = np.array(axis, ndmin = 1)
assert np.all(np.in1d(axs, np.arange(ashp.size))), "Axes out of range"
else:
axs = np.arange(ashp.size)

window = np.array(window, ndmin = 1)
assert (window.size == axs.size) | (window.size == 1), "Window dims and axes don't match"
wshp = ashp.copy()
wshp[axs] = window
assert np.all(wshp <= ashp), "Window is bigger than input array in axes"

stp = np.ones_like(ashp)
if steps:
steps = np.array(steps, ndmin = 1)
assert np.all(steps > 0), "Only positive steps allowed"
assert (steps.size == axs.size) | (steps.size == 1), "Steps and axes don't match"
stp[axs] = steps

astr = np.array(a.strides)

shape = tuple((ashp - wshp) // stp + 1) + tuple(wshp)
strides = tuple(astr * stp) + tuple(astr)

as_strided = np.lib.stride_tricks.as_strided
a_view = np.squeeze(as_strided(a,
shape = shape,
strides = strides))
if outlist:
return list(a_view.reshape((-1,) + tuple(wshp)))
else:
return a_view``````

``````a = np.arange(1000).reshape(10,10,10)

window_nd(a, 4).shape # sliding (4x4x4) window
Out: (7, 7, 7, 4, 4, 4)

window_nd(a, 2, 2).shape # (2x2x2) blocks
Out: (5, 5, 5, 2, 2, 2)

window_nd(a, 2, 1, 0).shape # sliding window of width 2 over axis 0
Out: (9, 2, 10, 10)

window_nd(a, 2, 2, (0,1)).shape # tiled (2x2) windows over first and second axes
Out: (5, 5, 2, 2, 10)

window_nd(a,(4,3,2)).shape  # arbitrary sliding window
Out: (7, 8, 9, 4, 3, 2)

window_nd(a,(4,3,2),(1,5,2),(0,2,1)).shape #arbitrary windows, steps and axis
Out: (7, 5, 2, 4, 2, 3) # note shape[-3:] != window as axes are out of order``````