仅沿一个轴卷积

时间:2011-03-08 05:31:10

标签: numpy signal-processing scipy linear-algebra convolution

我有两个具有相同第一轴尺寸的二维阵列。在python中,我想仅沿第二轴卷积两个矩阵。我想在C下方,而不是沿第一轴计算卷积。

import numpy as np
import scipy.signal as sg

M, N, P = 4, 10, 20
A = np.random.randn(M, N)
B = np.random.randn(M, P)

C = sg.convolve(A, B, 'full')[(2*M-1)/2]

有快节奏吗?

4 个答案:

答案 0 :(得分:10)

您可以使用np.apply_along_axis沿所需轴应用np.convolve。以下是将boxcar过滤器应用于2D阵列的示例:

import numpy as np

a = np.arange(10)
a = np.vstack((a,a)).T

filt = np.ones(3)

np.apply_along_axis(lambda m: np.convolve(m, filt, mode='full'), axis=0, arr=a)

这是一种简单的方法来概括许多没有axis参数的函数。

答案 1 :(得分:5)

np.apply_along_axis确实对您没有帮助,因为您正在尝试迭代两个数组。实际上,您必须使用循环,如here所述。

现在,如果您的数组很小,循环就可以了,但如果N和P很大,那么您可能希望使用FFT进行卷积。

但是,您需要先对阵列进行适当的零填充,以便您的#34;完整"卷积具有预期的形状:

M, N, P = 4, 10, 20
A = np.random.randn(M, N)
B = np.random.randn(M, P)

A_ = np.zeros((M, N+P-1), dtype=A.dtype)
A_[:, :N] = A
B_ = np.zeros((M, N+P-1), dtype=B.dtype)
B_[:, :P] = B

A_fft = np.fft.fft(A_, axis=1)
B_fft = np.fft.fft(B_, axis=1)
C_fft = A_fft * B_fft

C = np.real(np.fft.ifft(C_fft))

# Test
C_test = np.zeros((M, N+P-1))
for i in range(M):
    C_test[i, :] = np.convolve(A[i, :], B[i, :], 'full')

assert np.allclose(C, C_test)

答案 2 :(得分:4)

使用ndimage.convolve1d,您可以指定轴...

答案 3 :(得分:2)

对于2D数组,函数scipy.signal.convolve2d更快,scipy.signal.fftconvolve可以更快(取决于数组的维度):

这里的代码与N = 100000

相同
import time    
import numpy as np
import scipy.signal as sg

M, N, P = 10, 100000, 20
A = np.random.randn(M, N)
B = np.random.randn(M, P)

T1 = time.time()
C = sg.convolve(A, B, 'full')
print(time.time()-T1)

T1 = time.time()
C_2d = sg.convolve2d(A, B, 'full')
print(time.time()-T1)

T1 = time.time()
C_fft = sg.fftconvolve(A, B, 'full')
print(time.time()-T1)

>>> 12.3
>>> 2.1
>>> 0.6
由于使用了不同的计算方法(例如,fft与直接乘法,但我不知道exactlty convolve2d使用了什么),答案是完全一样的,但是有轻微差异:

print(np.max(np.abs(C - C_2d)))
>>>7.81597009336e-14

print(np.max(np.abs(C - C_fft)))
>>>1.84741111298e-13
相关问题