且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-10-17 10:44:10

scipy 有很多不同的方法可以做到,但是 numpy 中没有直接包含 2D 卷积代码>.(如果您需要避免 scipy 依赖,也可以很容易地使用仅使用 numpy 的 fft 来实现.)

There are a number of different ways to do it with scipy, but 2D convolution isn't directly included in numpy. (It's also easy to implement with an fft using only numpy, if you need to avoid a scipy dependency.)

scipy.signal.convolve2dscipy.signal.convolvescipy.signal.fftconvolvescipy.ndimage.convolve 都会以不同的方式处理 2D 卷积(最后三个是 Nd).

scipy.signal.convolve2d, scipy.signal.convolve, scipy.signal.fftconvolve, and scipy.ndimage.convolve will all handle a 2D convolution (the last three are N-d) in different ways.

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

scipy.signal.fftconvolve does the convolution in the fft domain (where it's a simple multiplication). This is much faster in many cases, but can lead to very small differences in edge effects than the discrete case, and your data will be coerced into floating point with this particular implementation. Additionally, there's unnecessary memory usage when convolving a small array with a much larger array. All in all, fft-based methods can be dramatically faster, but there are some common use cases where scipy.signal.fftconvolve is not an ideal solution.

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

scipy.signal.convolve2d, scipy.signal.convolve, and scipy.ndimage.convolve all use a discrete convolution implemented in C, however, they implement it in different ways.

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

scipy.ndimage.convolve keeps the same data type, and gives you control over the location of the output to minimize memory usage. If you're convolving uint8's (e.g. image data), it's often the best option. The output will always be the same shape as the first input array, which makes sense for images, but perhaps not for more general convolution. ndimage.convolve gives you a lot of control over how edge effects are handled through the mode kwarg (which functions completely differently than scipy.signal's mode kwarg).

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

Avoid scipy.signal.convolve if you're working with 2d arrays. It works for the N-d case, but it's suboptimal for 2d arrays, and scipy.signal.convolve2d exists to do the exact same thing a bit more efficiently. The convolution functions in scipy.signal give you control over the output shape using the mode kwarg. (By default, they'll behave just like matlab's conv2.) This is useful for general mathematical convolution, but less useful for image processing. However, scipy.signal.convolve2d is generally slower than scipy.ndimage.convolve.

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

There are a lot of different options partly due to duplication in the different submodules of scipy and partly because there are different ways to implement a convolution that have different performance tradeoffs.

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

If you can give a bit more detail about your use case, we can recommend a better solution. If you're convolving two arrays of roughly the same size, and they're already floats, fftconvolve is an excellent choice. Otherwise, scipy.ndimage.convolve may beat it.