15

我一直在尝试使用 SciPy 和 Numpy 对 2D 矩阵进行卷积,但失败了。对于我尝试过的 SciPy,sepfir2d 和 scipy.signal.convolve 以及用于 Numpy 的 Convolve2D。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 中计算这个输出的一些函数?我将不胜感激。

4

3 回答 3

31

有许多不同的方法可以做到这一点scipy,但 2D 卷积不直接包含在numpy. (如果您需要避免 scipy 依赖,仅使用 numpy 的 fft 也很容易实现。)

scipy.signal.convolve2d, scipy.signal.convolve,scipy.signal.fftconvolvescipy.ndimage.convolve都将以不同的方式处理 2D 卷积(最后三个是 Nd)。

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

scipy.signal.convolve2d, scipy.signal.convolve, 和scipy.ndimage.convolve所有使用 C 实现的离散卷积,但是,它们以不同的方式实现它。

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

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

有很多不同的选择,部分原因是不同子模块的重复,scipy部分原因是实现卷积的不同方法具有不同的性能权衡。

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

于 2013-04-20T15:22:30.747 回答
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 中所做的大部分工作(甚至更多)。

于 2013-04-20T15:14:22.733 回答
-4

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

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

于 2013-04-20T14:39:51.167 回答