2013-12-18 8 views
3

Чтение this и с попыткой np.correlate и cv2.matchTemplate У меня все еще есть вопрос, который я, похоже, не могу решить.Перекрестная корреляция множественных последовательностей, избегающих цикла

У меня есть два массива numpy, каждый из которых имеет форму (6000,50). 6000 последовательностей с каждыми 50 значениями. Теперь я хотел бы сделать кросс-корреляцию двух одномерных последовательностей этого массива для определения временного сдвига. Я попытался OpenCV кратко, но для меня это возвращает единственное число (я рассчитывать на самую высокую корреляцию), так что теперь я использую numpy.correlate так:

np.correlate(x[2500], y[2500], mode='same') 

(В кросс-корреляции сюжета я не ищу для самого высокого пика, но я ищу для первого пика с использованием this см. график для примера)

enter image description here

Как и следовало ожидать, я хотел бы сделать это для всех последовательностей 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

Почему вы хотите, чтобы избежать итераций? Даже если бы было что-то вроде того, чего вы хотите, оно просто упаковывает итерацию внутри. Сложность не будет ниже. – Skyler

+0

@Skyler, я подумал, возможно, это возможно с каким-то математическим вычислением. – Mattijn

+0

Ну, я вижу. Но я не знаю такой функции :-( – Skyler

ответ

3

scipy.ndimage.correlate1d казалось, что вы после этого, но она вещает только на первом массиве, то второй должен быть строго 1D, так не повезло там. И функции в scipy.signal выполняют многомерную корреляцию, а не 1D, как и вы. Таким образом, в стеке нет ничего, что могло бы решить вашу проблему.

Просто для удовольствия вы всегда можете сделать это с помощью БПФ и 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 
+0

Спасибо за ваш ответ. «Веселая» часть кажется очень полезной для больших последовательностей. Что-то, что может произойти в один прекрасный день! Что касается заполнения 1D-массивов нулевым или одним а затем применить одну из функций «scipy.signal»? – Mattijn

+0

Нет, функции 'scipy.signal' выполняют корреляцию в обоих направлениях, и вы не можете преодолеть это с помощью дополнения. Правильно, чтобы сделать, proper 'ndimage.correlate1d' ... – Jaime

+0

Хорошо Спасибо за объяснение. Позвольте мне написать запрос на numpy github, возможно, коррелят1d будет обновляться один день – Mattijn

 Смежные вопросы

  • Нет связанных вопросов^_^