2D-свертка и корреляция на основе FFT в Python
-
11-09-2019 - |
Вопрос
Есть ли функция 2D взаимной корреляции или свертки на основе FFT, встроенная в scipy (или другую популярную библиотеку)?
Существуют такие функции, как эти:
scipy.signal.correlate2d
- "прямой метод, реализованный с помощьюconvolveND
будет медленным для больших объемов данных"scipy.ndimage.correlate
- "Массив соотносится с данным ядром с помощью точного вычисления (т.е.не БПФ)."scipy.fftpack.convolve.convolve
, что я на самом деле не понимаю, но кажется неправильным
у numarray был correlate2d()
функционировать с помощью fft=True
переключатель, но я предполагаю, что numarray был свернут
в numpy, и я не могу найти, была ли включена эта функция.
Решение
Я нашел scipy.signal.fftconvolve
, как также указал магнус, но в то время не понимал, что это n-размерный.Поскольку он встроен и выдает правильные значения, это кажется идеальным решением.
In [1]: a = asarray([[ 1, 2, 3],
...: [ 4, 5, 6],
...: [ 7, 8, 9]])
In [2]: b = asarray([[-1,-2,-1],
...: [ 0, 0, 0],
...: [ 1, 2, 1]])
In [3]: scipy.signal.fftconvolve(a, b, mode = 'same')
Out[3]:
array([[-13., -20., -17.],
[-18., -24., -18.],
[ 13., 20., 17.]])
Правильно!Версия STSCI, с другой стороны, требует некоторой дополнительной работы, чтобы сделать границы правильными?
In [4]: stsci.convolve2d(a, b, fft = True)
Out[4]:
array([[-12., -12., -12.],
[-24., -24., -24.],
[-12., -12., -12.]])
(Метод STSCI также требует компиляции, с которой я потерпел неудачу (я просто закомментировал части, отличные от python), имеет некоторые ошибки, такие как это и изменяя входные данные ([1, 2] становится [[1, 2]]) и т.д.Поэтому я изменил свой общепринятый ответ на встроенный fftconvolve()
функция.)
Корреляция, конечно, - это то же самое, что свертка, но с одним обратным вводом:
In [5]: a
Out[5]:
array([[3, 0, 0],
[2, 0, 0],
[1, 0, 0]])
In [6]: b
Out[6]:
array([[3, 2, 1],
[0, 0, 0],
[0, 0, 0]])
In [7]: scipy.signal.fftconvolve(a, b[::-1, ::-1])
Out[7]:
array([[ 0., -0., 0., 0., 0.],
[ 0., -0., 0., 0., 0.],
[ 3., 6., 9., 0., 0.],
[ 2., 4., 6., 0., 0.],
[ 1., 2., 3., 0., 0.]])
In [8]: scipy.signal.correlate2d(a, b)
Out[8]:
array([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[3, 6, 9, 0, 0],
[2, 4, 6, 0, 0],
[1, 2, 3, 0, 0]])
и последняя редакция был ускорен за счет внутреннего использования размеров power-of-two (а затем я ускорил его еще больше за счет использование реального БПФ для реального ввода и использование 5-гладких длин вместо степеней 2 :D ).
Другие советы
посмотрите на scipy.signal.fftconvolve, signal.convolve и signal.correlate (есть signal.correlate2d, но, похоже, он возвращает сдвинутый массив, а не центрированный).
Я думаю, вам нужен пакет scipy.stsci:
http://docs.scipy.org/doc/scipy/reference/stsci.html
In [30]: scipy.__version__
Out[30]: '0.7.0'
In [31]: from scipy.stsci.convolve import convolve2d, correlate2d
Я потерял информацию о статусе этого пакета в scipy, но я знаю, что мы включаем ndimage как часть пакета выпуска stsci_python для удобства наших пользователей:
http://www.stsci.edu/resources/software_hardware/pyraf/stsci_python/current/download
или вы должны иметь возможность извлечь его из репозитория, если хотите:
https://www.stsci.edu/svn/ssb/stsci_python/stsci_python/trunk/ndimage/
Я написал оболочку взаимной корреляции / свертки, которая заботится о заполнении и nans и включает в себя простую гладкую оболочку здесь.Это не популярный пакет, но у него также нет зависимостей, кроме numpy (или fftw для более быстрого fft).
Я также внедрил код тестирования скорости FFT здесь на случай, если кому-то будет интересно.Это показывает - удивительно, - что fft numpy работает быстрее, чем scipy, по крайней мере, на моей машине.
Редактировать:перенесен код в N-мерную версию здесь