阅读this并尝试了np.correlate和cv2.matchTemplate我仍然有一个我似乎无法解决的问题。
我有两个numpy数组,每个数组的形状为(6000,50)
。 6000个序列,每个50个值。现在我想对这个数组的两个1维序列进行互相关以检测时移。我简单地尝试了openCV,但对我来说这会返回一个数字(我期望最高的相关性),所以现在我使用像这样的numpy.correlate:
np.correlate(x[2500], y[2500], mode='same')
(在互相关图中,我不是在寻找最高峰,但我正在寻找使用this的第一个峰值。参见情节示例)
正如您所料,我想为所有6000个序列执行此操作,但希望避免迭代。我希望这会奏效:
np.correlate(x, y, mode='same')
但是这给了我以下错误:ValueError: object too deep for desired array
。
NumPy或OpenCV是否有任何变化。或者我必须这样做:(
for i in range(x.shape[0]):
np.correlate(x[i], y[i], mode='same')
答案 0 :(得分:3)
scipy.ndimage.correlate1d
似乎就像你所追求的那样,但它只在第一个阵列上广播,第二个必须严格1D,所以那里没有运气。并且scipy.signal
中的函数执行多维关联,而不是像您所追求的那样1D。因此,堆栈中似乎没有任何东西可以解决您的问题。
只是为了它的乐趣,你总是可以使用FFT和cross-correlation theorem来做到这一点:
def correlate1(a, b):
c = np.empty_like(a)
for j in range(len(a)):
c[j] = np.correlate(a[j], b[j], 'same')
return c
def correlate2(a, b):
n = a.shape[-1]
a_fft = np.fft.fft(a, n=2*n)
b_fft = np.fft.fft(b, n=2*n)
cc = np.fft.ifft(a_fft * b_fft.conj()).real
return np.concatenate((cc[..., -n//2:], cc[..., :(n-1)//2 + 1]), axis=-1)
根据您的使用案例,这不是一个好主意:
In [11]: a = np.random.rand(6000, 50)
...: b = np.random.rand(6000, 50)
...:
In [12]: np.allclose(correlate1(a, b), correlate2(a, b))
Out[12]: True
In [13]: %timeit correlate1(a, b)
10 loops, best of 3: 37.5 ms per loop
In [14]: %timeit correlate2(a, b)
10 loops, best of 3: 71.8 ms per loop
但这种方法确实有其优点,主要用于较大的序列:
In [15]: a = np.random.rand(50, 6000)
...: b = np.random.rand(50, 6000)
...:
In [16]: %timeit correlate1(a, b)
1 loops, best of 3: 516 ms per loop
In [17]: %timeit correlate2(a, b)
10 loops, best of 3: 89.2 ms per loop