2013-08-11 4 views
3

Я хочу свернуть n-мерное изображение, концептуально периодическое.Сопряжение периодического изображения с питоном

То, что я имею в виду следующее: если у меня есть 2D изображение

>>> image2d = [[0,0,0,0], 
...   [0,0,0,1], 
...   [0,0,0,0]] 

и я хочу свертку его с этим ядром:

>>> kernel = [[ 1,1,1], 
...   [ 1,1,1], 
...   [ 1,1,1]] 

, то я хочу, чтобы результат:

>>> result = [[1,0,1,1], 
...   [1,0,1,1], 
...   [1,0,1,1]] 

Как это сделать в python/numpy/scipy?

Обратите внимание, что я не заинтересован в создании ядра, но в основном периодичность свертки, т. Е. Три левых в полученном изображении (если это имеет смысл).

+0

Я думаю, вам придется свернуть свой собственный код, довольно легко с помощью БПФ и [теорему о свертке] (http://en.wikipedia.org/wiki/Convolution_theorem). Единственная сложная часть может заключаться в том, как проложить ядро, чтобы получить правильный ответ. – Jaime

ответ

1

Этот вид «периодической свертки» более известен как круговая или циклическая свертка. См. http://en.wikipedia.org/wiki/Circular_convolution.

В случае n-мерного изображения, как в случае с этим вопросом, можно использовать функцию scipy.ndimage.convolve. Он имеет параметр режим, который может быть установлен на wrap для круговой свертки.

result = scipy.ndimage.convolve(image,kernel,mode='wrap') 

>>> import numpy as np 
>>> image = np.array([[0, 0, 0, 0], 
...     [0, 0, 0, 1], 
...     [0, 0, 0, 0]]) 
>>> kernel = np.array([[1, 1, 1], 
...     [1, 1, 1], 
...     [1, 1, 1]]) 
>>> from scipy.ndimage import convolve 
>>> convolve(image, kernel, mode='wrap') 
array([[1, 0, 1, 1], 
     [1, 0, 1, 1], 
     [1, 0, 1, 1]]) 
+0

[scipy.signal.fftconvolve] (http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.fftconvolve.html) не поддерживает режим ''wrap''. – askewchan

+0

Нет, но он выполняет круговую свертку. – ABDreverhaven

+0

В моей системе нет круговых условий, а не с любыми режимами, перечисленными в документации. Просто не забудьте проверить все эти образцы перед использованием данных. – askewchan

2
image2d = [[0,0,0,0,0], 
      [0,0,0,1,0], 
      [0,0,0,0,0], 
      [0,0,0,0,0]] 
kernel = [[1,1,1], 
      [1,1,1], 
      [1,1,1]] 
image2d = np.asarray(image2d) 
kernel = np.asarray(kernel) 

img_f = np.fft.fft2(image2d) 
krn_f = np.fft.fft2(kernel, s=image2d.shape) 

conv = np.fft.ifft2(img_f*krn_f).real 

>>> conv.round() 
array([[ 0., 0., 0., 0., 0.], 
     [ 1., 0., 0., 1., 1.], 
     [ 1., 0., 0., 1., 1.], 
     [ 1., 0., 0., 1., 1.]]) 

Обратите внимание, что ядро ​​размещается в верхнем левом углу в положении 1 на изображении. Вы должны были бы катиться результат, чтобы получить то, что вы после:

k_rows, k_cols = kernel.shape 
conv2 = np.roll(np.roll(conv, -(k_cols//2), axis=-1), 
       -(k_rows//2), axis=-2) 
>>> conv2.round() 
array([[ 0., 0., 1., 1., 1.], 
     [ 0., 0., 1., 1., 1.], 
     [ 0., 0., 1., 1., 1.], 
     [ 0., 0., 0., 0., 0.]]) 
3

Это уже встроены, с scipy.signal.convolve2d «s опциональный boundary='wrap' которая дает периодические граничные условия, дополнения для свертки. Опция mode здесь 'same', чтобы размер выходного файла соответствовал размеру ввода.

In [1]: image2d = [[0,0,0,0], 
    ...   [0,0,0,1], 
    ...   [0,0,0,0]] 

In [2]: kernel = [[ 1,1,1], 
    ...   [ 1,1,1], 
    ...   [ 1,1,1]] 

In [3]: from scipy.signal import convolve2d 

In [4]: convolve2d(image2d, kernel, mode='same', boundary='wrap') 
Out[4]: 
array([[1, 0, 1, 1], 
     [1, 0, 1, 1], 
     [1, 0, 1, 1]]) 

Единственным недостатком является то, что вы не можете использовать scipy.signal.fftconvolve, который часто работает быстрее.

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