Python中的2D卷积类似于Matlab的conv2

use*_*318 16 python matlab signal-processing image convolution

我一直在尝试使用SciPy进行2D矩阵的卷积,而Numpy却失败了.对于SciPy我试过,sepfir2d和scipy.signal.convolve和Convolve2D for Numpy.在Matlab for Python中是否有像conv2这样的简单函数?

这是一个例子:

 A= [ 5     4     5     4;
      3     2     3     2;
      5     4     5     4;
      3     2     3     2 ]
Run Code Online (Sandbox Code Playgroud)

我想把它卷入其中 [0.707 0.707]

而来自Matlab的conv2的结果是

3.5350    6.3630    6.3630    6.3630    2.8280
2.1210    3.5350    3.5350    3.5350    1.4140
3.5350    6.3630    6.3630    6.3630    2.8280
2.1210    3.5350    3.5350    3.5350    1.4140
Run Code Online (Sandbox Code Playgroud)

有些函数用Python来计算这个输出吗?我将感激回应.

Joe*_*ton 31

有许多不同的方法可以实现scipy,但2D卷积不直接包含在内numpy.(如果你需要避免scipy依赖,那么只使用numpy也很容易实现fft.)

scipy.signal.convolve2d,scipy.signal.convolve,scipy.signal.fftconvolve,并且scipy.ndimage.convolve将所有处理二维卷积(最后三个Nd)的方式不同.

scipy.signal.fftconvolve在fft域中进行卷积(这是一个简单的乘法).在许多情况下,这种速度要快得多,但是与边缘情况相比,边缘效应会产生非常小的差异,并且您的数据将通过此特定实现强制转换为浮点数.此外,在使用更大的阵列卷积小阵列时,会有不必要的内存使用.总而言之,基于fft的方法可以大大加快,但是有一些常见的用例scipy.signal.fftconvolve并不是理想的解决方案.

scipy.signal.convolve2d,scipy.signal.convolve并且scipy.ndimage.convolve都使用在C中实现的离散卷积,但是,它们以不同的方式实现它.

scipy.ndimage.convolve保持相同的数据类型,并让您控制输出的位置,以最大限度地减少内存使用.如果你正在卷积uint8(例如图像数据),它通常是最好的选择.输出将始终与第一个输入数组的形状相同,这对图像有意义,但可能不适用于更一般的卷积.ndimage.convolve让你在边缘效应如何通过处理大量的控制modekwarg(其功能比完全不同scipy.signalmodekwarg).

scipy.signal.convolve如果你正在使用2d数组,请避免使用.它适用于Nd情况,但它对于2d数组来说是次优的,并且scipy.signal.convolve2d存在更高效地执行完全相同的操作.卷积函数可scipy.signal让您使用modekwarg 控制输出形状.(默认情况下,它们的行为与matlab类似conv2.)这对于一般的数学卷积非常有用,但对图像处理不太有用.但是,scipy.signal.convolve2d通常比慢scipy.ndimage.convolve.

有许多不同的选项部分是由于不同子模块中的重复scipy,部分是因为有不同的方法来实现具有不同性能权衡的卷积.

如果您可以提供有关用例的更多详细信息,我们可以推荐更好的解决方案.如果您正在卷积两个大小相同的阵列,并且它们已经是浮动的,那么这fftconvolve是一个很好的选择.否则,scipy.ndimage.convolve可能打败它.


Bit*_*ise 5

scipy的convolved1d()做你想要的,只是区别对待边缘:

sp.ndimage.filters.convolve1d(A,[0.707,0.707],axis=1,mode='constant')
Run Code Online (Sandbox Code Playgroud)

会给你:

array([[ 6.363,  6.363,  6.363,  2.828],
       [ 3.535,  3.535,  3.535,  1.414],
       [ 6.363,  6.363,  6.363,  2.828],
       [ 3.535,  3.535,  3.535,  1.414]])
Run Code Online (Sandbox Code Playgroud)

如果你想要完全相同的结果,只需在A中添加一列零,如下所示:

sp.ndimage.filters.convolve1d(np.c_[np.zeros((4,1)),A],[0.707,0.707],axis=1,mode='constant')
Run Code Online (Sandbox Code Playgroud)

你会得到:

array([[ 3.535,  6.363,  6.363,  6.363,  2.828],
       [ 2.121,  3.535,  3.535,  3.535,  1.414],
       [ 3.535,  6.363,  6.363,  6.363,  2.828],
       [ 2.121,  3.535,  3.535,  3.535,  1.414]])
Run Code Online (Sandbox Code Playgroud)

根据我的经验,你可以用scipy/numpy做很多你在Matlab中做的很容易(甚至更多).


Dan*_*rin -4

为什么不自己实现呢?请注意,conv2 使用空间形式的二维卷积方程的简单形式实现。如果a和b是两个离散变量n1和n2的函数,则a和b的二维卷积公式为: 在此输入图像描述

但实际上, conv2 计算有限间隔的卷积。

  • 我当然可以,如果我还没有找到办法,我一定找到了。但我想我的实现不会被优化,所以我正在寻找一个包。 (6认同)
  • @Daniel - 因为当已经有工具可以为您计算卷积时,您建议的是一个相当低效的解决方案。另外,从OP问题的上下文来看,他们想使用一个包。我没有对你投反对票,但如果我感觉不好,我会的。 (3认同)