对于图像,我使用两种方式使用中心有限差分实现了第一个空间导数(沿着任意维度):(1)使用具有中心有限差分内核的scipy.ndimage.filters.convolve
和(2)使用数组切片计算差异。
我确信(2)一般会更快,它适用于2D图像,但对于大型3D图像,(1)肯定更快。我不敢相信DFT +乘法比一堆减法更快。谁能解释一下呢?
代码(1):
import numpy as np
import scipy.ndimage.filters as ndif
_MASK = np.array([1.0, 0.0, -1.0])
def partial(img, vox, axis, mode='wrap'):
"""Return partial derivative of *img* w.r.t. *axis* direction"""
d = len(img.shape)
shm = np.identity(d)*2 + 1
m = np.reshape(_MASK, shm[axis])/(2.0*vox[axis])
return ndif.convolve(img, m, mode=mode)
代码为(2):
import numpy as np
so0 = slice(None, None, None)
so1 = slice(None, -2, None)
so2 = slice(2, None, None)
def partial(img, vox, axis, mode='wrap'):
"""Return partial derivative of *img* w.r.t. *axis* direction"""
d = len(img.shape)
soa = [so0]*d
soa[axis] = so1
sob = [so0]*d
sob[axis] = so2
p = [(0, 0)]*d
p[axis] = (1, 1)
imga = np.pad(img, p, mode='constant')
return (imga[sob] - imga[soa])/(2.0*vox[axis])
timeit测试和结果(vcalc
实现(1)和vcalc_up
实现(2); gradient
只是在每个图片维度上调用partial
:
import timeit
setup = """
import numpy as np
import vcalc
import vcalc_up
# Build zero padded 3d image similar to real MRI input
d = 3
so = [slice(20, -20, None)]*d
tmp = np.zeros((220,)*d)
tmp[so] = np.random.random((180,)*d)
vox = [1e-1]*d
"""
r = 5
i = 100
stmt = "vcalc.gradient(tmp, vox)"
tl = timeit.Timer(stmt, setup).repeat(r, i)
print tl
stmt = "vcalc_up.gradient(tmp, vox)"
tl = timeit.Timer(stmt, setup).repeat(r, i)
print tl
输出:
[60.21655583381653, 59.78620195388794, 60.69061803817749, 59.873075008392334, 60.28675389289856]
[84.67993712425232, 83.95580792427063, 84.6122419834137, 84.67212200164795, 84.78972506523132]