图像第一个空间导数,SciPy Ndimage比阵列切片更快地过滤卷积?

时间:2016-05-18 16:44:23

标签: numpy scipy convolution calculus dft

对于图像,我使用两种方式使用中心有限差分实现了第一个空间导数(沿着任意维度):(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]

0 个答案:

没有答案