我一直在尝试使用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中计算此输出的一些函数?我将非常感谢您的回复。
答案 0 :(得分:31)
使用scipy
进行此操作有多种方法,但2D卷积不会直接包含在numpy
中。 (如果你需要避免scipy依赖,那么只使用numpy很容易实现fft。)
scipy.signal.convolve2d
,scipy.signal.convolve
,scipy.signal.fftconvolve
和scipy.ndimage.convolve
将以不同的方式处理2D卷积(后三个是N-d)。
scipy.signal.fftconvolve
在fft域中进行卷积(它是一个简单的乘法)。在许多情况下,这种速度要快得多,但是与边缘情况相比,边缘效应会产生非常小的差异,并且您的数据将通过此特定实现强制转换为浮点数。此外,当使用更大的阵列卷积小阵列时,会有不必要的内存使用。总而言之,基于fft的方法可以大大加快,但是有一些常见的用例scipy.signal.fftconvolve
不是理想的解决方案。
scipy.signal.convolve2d
,scipy.signal.convolve
和scipy.ndimage.convolve
都使用在C中实现的离散卷积,但是,它们以不同的方式实现它。
scipy.ndimage.convolve
保持相同的数据类型,并使您可以控制输出的位置以最大限度地减少内存使用。如果您要回复uint8
(例如图片数据),它通常是最佳选择。输出将始终与第一个输入数组的形状相同,这对图像有意义,但可能不适用于更一般的卷积。 ndimage.convolve
通过mode
kwarg(其功能与scipy.signal
' 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的二维卷积的公式是:
然而,在实践中,conv2计算有限区间的卷积。