Python中速度最快的2D卷积或图像滤镜

Car*_* F. 20 python optimization numpy scipy python-imaging-library

几个用户询问在numpy的或SciPy的图像卷积的速度或存储器消耗[ 1,2,3,4 ].从回答和我使用Numpy的经验来看,我相信与Matlab或IDL相比,这可能是numpy的一个主要缺点.

到目前为止,答案都没有解决整个问题,所以这里是:"在Python中计算2D卷积的最快方法是什么?" 常见的python模块是公平游戏:numpy,scipy和PIL(其他?).为了进行具有挑战性的比较,我想提出以下规则:

  1. 输入矩阵分别为2048x2048和32x32.
  2. 单精度或双精度浮点都是可以接受的.
  3. 将输入矩阵转换为适当格式所花费的时间不计算 - 只是卷积步骤.
  4. 用你的输出替换输入矩阵是可以接受的(任何python库支持吗?)
  5. 对常见C库的直接DLL调用是好的 - lapack或scalapack
  6. PyCUDA就出局了.使用自定义GPU硬件是不公平的.

Sve*_*ach 12

在我的机器上,使用FFT的手工制作的循环卷积似乎很禁止:

import numpy
x = numpy.random.random((2048, 2048)).astype(numpy.float32)
y = numpy.random.random((32, 32)).astype(numpy.float32)
z = numpy.fft.irfft2(numpy.fft.rfft2(x) * numpy.fft.rfft2(y, x.shape))
Run Code Online (Sandbox Code Playgroud)

请注意,这可能会以不同于其他方式的方式处理靠近边缘的区域,因为它是循环卷积.


Joe*_*ton 10

这实际上取决于你想要做什么...很多时候,你不需要一个完全通用的(读取:慢速)2D卷积...(即如果过滤器是可分离的,你使用两个1D卷积代替......这就是为什么各种各样的scipy.ndimage.gaussian,scipy.ndimage.uniform比通用的nD卷积更快的原因.)

无论如何,作为比较点:

t = timeit.timeit(stmt='ndimage.convolve(x, y, output=x)', number=1,
setup="""
import numpy as np
from scipy import ndimage
x = np.random.random((2048, 2048)).astype(np.float32)
y = np.random.random((32, 32)).astype(np.float32)
""")
print t
Run Code Online (Sandbox Code Playgroud)

我的机器需要6.9秒...

比较这个 fftconvolve

t = timeit.timeit(stmt="signal.fftconvolve(x, y, mode='same')", number=1,
setup="""
import numpy as np
from scipy import signal
x = np.random.random((2048, 2048)).astype(np.float32)
y = np.random.random((32, 32)).astype(np.float32)
""")
print t
Run Code Online (Sandbox Code Playgroud)

这需要大约10.8秒.但是,使用不同的输入大小,使用fft进行卷积可以相当快(虽然我似乎无法想出一个很好的例子,目前......).

  • 对于那些感兴趣.我比原始帖子晚5年做了这个比较(OS X 10.10 Macbook Air).`signal.fftconvolve`需要大约**.9秒**!`ndimage.convolve`需要大约**8秒**.显然,在引擎盖下的`signal.fftconvolve`上进行了巨大的改进. (6认同)