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

时间:2013-04-20 14:12:18

标签: python image matlab signal-processing 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 ]

我想将其与[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

在Python中计算此输出的一些函数?我将非常感谢您的回复。

3 个答案:

答案 0 :(得分:31)

使用scipy进行此操作有多种方法,但2D卷积不会直接包含在numpy中。 (如果你需要避免scipy依赖,那么只使用numpy很容易实现fft。)

scipy.signal.convolve2dscipy.signal.convolvescipy.signal.fftconvolvescipy.ndimage.convolve将以不同的方式处理2D卷积(后三个是N-d)。

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

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

scipy.ndimage.convolve保持相同的数据类型,并使您可以控制输出的位置以最大限度地减少内存使用。如果您要回复uint8(例如图片数据),它通常是最佳选择。输出将始终与第一个输入数组的形状相同,这对图像有意义,但可能不适用于更一般的卷积。 ndimage.convolve通过mode kwarg(其功能与scipy.signal&#39; s mode kwarg完全不同)为您提供了对边缘效果处理方式的大量控制。< / p>

如果您正在使用2d数组,请避免使用scipy.signal.convolve。它适用于N-d情况,但它对于2d数组来说不是最理想的,并且存在scipy.signal.convolve2d来更有效地完成同样的事情。 scipy.signal中的卷积函数可让您使用mode kwarg控制输出形状。 (默认情况下,它们的行为与matlab的conv2一样。)这对于一般的数学卷积很有用,但对图像处理不太有用。但是,scipy.signal.convolve2d通常比scipy.ndimage.convolve慢。

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

如果您可以提供有关您的用例的更多详细信息,我们可以推荐更好的解决方案。如果您要对两个大小相同的数组进行卷积,并且它们已经浮动,fftconvolve是一个很好的选择。否则,scipy.ndimage.convolve可能会击败它。

答案 1 :(得分:5)

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

sp.ndimage.filters.convolve1d(A,[0.707,0.707],axis=1,mode='constant')

会给你:

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]])

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

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

你会得到:

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]])

根据我的经验,你可以很容易地做scipy / numpy你在Matlab中做的大部分事情(以及更多)。

答案 2 :(得分:-5)

为什么不自己实现?,请注意,conv2使用空间形式的二维卷积方程的直接形式实现。如果a和b是两个离散变量n1和n2的函数,那么a和b的二维卷积的公式是: enter image description here

然而,在实践中,conv2计算有限区间的卷积。