numpy数组上的可分离过滤器

Val*_*ntz 5 python arrays numpy image-processing gil

假设我有一个numpy数组a,我想创建一个新的数组,bb[i, j]是一个函数,比如说:

a[i-1, j-1], a[i-1, j  ], a[i-1, j+1],
a[i  , j-1], a[i  , j  ], a[i  , j+1],
a[i+1, j-1], a[i+1, j  ], a[i+1, j+1]
Run Code Online (Sandbox Code Playgroud)

最快的方法是什么?

由于这是一个可分离的过滤器,有没有办法在多个线程中运行它?(不是进程,因为我必须将数据复制回来)

或者正在编写C代码以绕过GIL强制执行?

部分解决方案(如假设功能是线性的)也是受欢迎的.

hpa*_*ulj 1

使用此类滑动窗口的理想numpy方法是构造一个 4D 数组

C.shape = (N,M,3,3)
Run Code Online (Sandbox Code Playgroud)

在哪里

C[i,j,:,:] = np.array([a[i-1, j-1], a[i-1, j  ], a[i-1, j+1],
                       a[i  , j-1], a[i  , j  ], a[i  , j+1],
                       a[i+1, j-1], a[i+1, j  ], a[i+1, j+1]])
Run Code Online (Sandbox Code Playgroud)

并编写您的函数,对最后两个维度进行某种缩减。 sum或者mean是典型的,例如

B = C.sum(axis=(2,3))
Run Code Online (Sandbox Code Playgroud)

其他 SO 问题展示了如何使用np.lib.stride_tricks.as_strided来构造这样的数组。但如果只有 3x3 子数组,执行类似操作可能会同样快

C = np.zeros((N,M,3,3))
C[:,:,0,0] = a[:-1,:-1]
etc.
Run Code Online (Sandbox Code Playgroud)

(或使用hstackandvstack达到相同的效果)。

但是跨步方法的一个好处(或者可能不太好)是它不涉及复制任何数据a- 它只是一个视图。

至于将工作分成几部分,我可以想象使用切片C(在第一个二维上),例如

 C[0:100,0:100,:,:].sum(axis=(2,3))
Run Code Online (Sandbox Code Playgroud)