scipy.ndimage.correlate 但在计算时更新值

问题描述

我需要一个 3x3 相邻单元的总和数组,其乘积基于具有相同大小的不同数组的内核(到目前为止正好是 scipy.ndimage.correlate)。但是当计算新数组的值时,它必须立即更新,而不是使用原始数组中的值进行下一次涉及该值的计算。我已经编写了这个缓慢的代码来自己实现它,它运行得非常好(虽然对我来说太慢了)并提供了预期的结果:

for x in range(width):
    for y in range(height):
        AArr[y,x] += laplaceNeighborDifference(x,y)

def laplaceNeighborDifference(x,y,z):
    global w,h,AArr
    return -AArr[y,x]+AArr[(y+1)%h,x]*.2+AArr[(y-1)%h,x]*.2+AArr[y,(x+1)%w]*.2+AArr[y,(x-1)%w]*.2+AArr[(y+1)%h,(x+1)%w]*.05+AArr[(y-1)%h,(x+1)%w]*.05+AArr[(y+1)%h,(x-1)%w]*.05+AArr[(y-1)%h,(x-1)%w]*.05

在我的方法中,内核是直接编码的。虽然作为一个数组(用作内核)它会写成这样:

[[.05,.2,.05],[.2,-1,.2 ],[.05,.05]]

SciPy 实现的工作方式如下:

AArr += correlate(AArr,kernel,mode='wrap')

但很明显,当我使用 scipy.ndimage.correlate 时,它完全根据原始数组计算值,并且在计算它们时不会更新它们。至少我认为这是我的实现和 SciPy 实现之间的区别,如果我遗漏了其他差异,请随时指出其他差异。我的问题是是否有与上述类似的功能并具有所需的结果,或者是否有一种比我更快的编码方法

感谢您的宝贵时间!

解决方法

您可以使用 Numba 来高效地做到这一点:

import numba as nb

@nb.njit
def laplaceNeighborDifference(AArr,w,h,x,y):
    return -AArr[y,x]+AArr[(y+1)%h,x]*.2+AArr[(y-1)%h,x]*.2+AArr[y,(x+1)%w]*.2+AArr[y,(x-1)%w]*.2+AArr[(y+1)%h,(x+1)%w]*.05+AArr[(y-1)%h,(x+1)%w]*.05+AArr[(y+1)%h,(x-1)%w]*.05+AArr[(y-1)%h,(x-1)%w]*.05

@nb.njit('void(float64[:,::1],int64,int64)')
def compute(AArr,width,height):
    for x in range(width):
        for y in range(height):
            AArr[y,x] += laplaceNeighborDifference(AArr,height,y)

请注意,模量通常很慢。最好通过单独计算主循环的边界来删除它们。生成的代码应该快得多,没有任何模数。