【问题标题】:Cross correlation of multiple sequences avoiding for loop避免for循环的多个序列的互相关
【发布时间】:2014-01-06 12:41:13
【问题描述】:

阅读 this 并尝试了 np.correlate 和 cv2.matchTemplate 我仍然有一个我似乎无法解决的问题。

我有两个 numpy 数组,每个数组的形状都为 (6000,50)。 6000 个序列,每 50 个值。现在我想做这个数组的两个一维序列的互相关来检测时移。我简单地尝试了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')

【问题讨论】:

  • 为什么要避免迭代?即使有你想要的东西,它也只是将迭代打包在里面。复杂度不会更低。
  • @Skyler,我想这可能与某种矩阵计算有关。
  • 嗯,我明白了。但是我不知道这样的功能:-(

标签: python opencv numpy cross-correlation


【解决方案1】:

scipy.ndimage.correlate1d 似乎是你所追求的,但它只在第一个数组上广播,第二个必须是严格的一维,所以那里没有运气。而scipy.signal 中的函数是多维相关的,而不是像你所追求的一维。因此,堆栈中似乎没有任何东西可以解决您的问题。

只是为了好玩,您总是可以使用 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

【讨论】:

  • 感谢您的回复。 “有趣”的部分似乎对更大的序列非常有用。某天可能发生的事情!用零或一填充一维数组然后应用“scipy.signal”函数之一怎么样?
  • 不,scipy.signal 函数会在两个方向上进行关联,而您无法通过填充来克服这一点。正确的做法是拥有一个适当的ndimage.correlate1d...
  • 好的。谢谢你的解释。让我在numpy github上写一个请求,也许有一天会更新correlate1d
猜你喜欢
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 2011-06-21
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多