2013-04-20 12 views
16

Próbowałem wykonać Konwolucji 2D Matrycy używając SciPy i Numpy, ale zawiodłem. Dla SciPy próbowałem, sepfir2d i scipy.signal.convolve i Convolve2D for Numpy. Czy istnieje prosta funkcja, taka jak conv2 w Matlab dla Pythona?Konwolucja 2D w Pythonie podobna do konw. Matlaba

Oto przykład:

A= [ 5  4  5  4; 
     3  2  3  2; 
     5  4  5  4; 
     3  2  3  2 ] 

Chcę convolve go [0.707 0.707]

A wynik jak przez conv2 z Matlab jest

3.5350 6.3630 6.3630 6.3630 2.8280 
2.1210 3.5350 3.5350 3.5350 1.4140 
3.5350 6.3630 6.3630 6.3630 2.8280 
2.1210 3.5350 3.5350 3.5350 1.4140 

Niektóre funkcje do obliczania tego wyjścia w Pyton? Będę wdzięczny za odpowiedź.

Odpowiedz

-5

Dlaczego nie zaimplementować go samodzielnie ?, zauważ, że conv2 stosuje prostą formalną implementację dwuwymiarowego równania splotu w formie przestrzennej. Jeśli A i B są funkcją dwóch zmiennych dyskretnych, N1 i N2, następnie preparat do dwuwymiarowego splotu A i B oznacza: enter image description here

W praktyce jednak conv2 oblicza splot o skończonych interwałach.

+5

Mogę oczywiście i jeśli nie znalazłem sposobu, muszę. Ale myślę, że moja implementacja nie zostanie zoptymalizowana, więc szukam pakietu. – user1343318

+0

@downvoter: Proszę, czy mógłbyś wyjaśnić, dlaczego spadki? – Daniel

+3

@Daniel - Ponieważ sugerujesz raczej nieefektywne rozwiązanie, gdy są już dostępne narzędzia do obliczenia splotu dla ciebie. Ponadto, sądząc z kontekstu pytania OP, chcą skorzystać z pakietu. Nie scharakteryzowałem cię, ale gdybym źle się poczuł, zrobiłbym to. – rayryeng

5

convolved1d scipy za() robi to, co chcesz, tylko traktuje krawędzie nieco inaczej:

sp.ndimage.filters.convolve1d(A,[0.707,0.707],axis=1,mode='constant') 

daje:

array([[ 6.363, 6.363, 6.363, 2.828], 
     [ 3.535, 3.535, 3.535, 1.414], 
     [ 6.363, 6.363, 6.363, 2.828], 
     [ 3.535, 3.535, 3.535, 1.414]]) 

Jeśli chcesz dokładnie ten sam wynik, po prostu dodaj kolumna zer na a tak:

sp.ndimage.filters.convolve1d(np.c_[np.zeros((4,1)),A],[0.707,0.707],axis=1,mode='constant') 

a dostaniesz:

array([[ 3.535, 6.363, 6.363, 6.363, 2.828], 
     [ 2.121, 3.535, 3.535, 3.535, 1.414], 
     [ 3.535, 6.363, 6.363, 6.363, 2.828], 
     [ 2.121, 3.535, 3.535, 3.535, 1.414]]) 

Z mojego doświadczenia wynika, że ​​możesz zrobić w scipy/numpy większość tego, co robisz w Matlab bardzo łatwo (i więcej).

+0

Dzięki tony Bitwise, zamierzam spróbować. – user1343318

30

Istnieje wiele różnych sposobów, aby to zrobić z scipy, ale splot 2D nie jest bezpośrednio zawarty w numpy. (Jest to również łatwe do wdrożenia z FFT używając jedynie numpy, jeśli chcesz uniknąć scipy zależność.)

scipy.signal.convolve2d, scipy.signal.convolve, scipy.signal.fftconvolve i scipy.ndimage.convolve będzie wszystko obsługiwać 2D splot (trzy ostatnie są Nd) w różnych sposoby.

scipy.signal.fftconvolve wykonuje splot w domenie fft (gdzie jest to proste mnożenie). W wielu przypadkach jest to znacznie szybsze, ale może prowadzić do bardzo niewielkich różnic w efektach krawędziowych w porównaniu do pojedynczego przypadku, a dane będą wymuszane na zmiennoprzecinkowe z tą konkretną implementacją. Ponadto niepotrzebne zużycie pamięci występuje podczas łączenia małej macierzy ze znacznie większą tablicą. Podsumowując, metody oparte na fft mogą być znacznie szybsze, ale istnieją pewne typowe przypadki użycia, w których scipy.signal.fftconvolve nie jest idealnym rozwiązaniem.

scipy.signal.convolve2d, scipy.signal.convolve i scipy.ndimage.convolve wszystkie używają dyskretnego splotu zaimplementowanego w C, jednak implementują go na różne sposoby.

scipy.ndimage.convolve zachowuje ten sam typ danych i daje kontrolę nad położeniem wyjścia, aby zminimalizować wykorzystanie pamięci. Jeśli konwertujesz uint8 (np. Dane obrazu), często jest to najlepsza opcja. Dane wyjściowe będą zawsze miały taki sam kształt jak pierwsza tablica wejściowa, co ma sens w przypadku obrazów, ale może nie w przypadku bardziej ogólnego splotu. ndimage.convolve daje dużą kontrolę nad tym, jak efekty brzegowe są obsługiwane za pomocą kwarg (który działa zupełnie inaczej niż 'skwarg).

Unikaj scipy.signal.convolve, jeśli pracujesz z tablicami 2d. Działa dla przypadku N-d, ale jest nieoptymalny dla macierzy 2d, a scipy.signal.convolve2d istnieje, aby wykonać to samo nieco bardziej wydajnie. Funkcje splotowe w scipy.signal dają kontrolę nad kształtem wyjściowym przy użyciu kwarg z zakresu mode. (Domyślnie zachowują się tak, jak w matlab: conv2.) Jest to przydatne w przypadku ogólnego splatania matematycznego, ale mniej przydatne do przetwarzania obrazu. Jednak scipy.signal.convolve2d jest zwykle wolniejszy niż scipy.ndimage.convolve.

Istnieje wiele różnych opcji, częściowo ze względu na powielanie w różnych submodułach scipy, a częściowo dlatego, że istnieją różne sposoby realizacji splotów, które mają różną wydajność.

Jeśli możesz podać nieco więcej szczegółów na temat swojego przypadku użycia, możemy polecić lepsze rozwiązanie. Jeśli łączysz dwie tablice o mniej więcej tym samym rozmiarze, a one już są pływające, fftconvolve to doskonały wybór. W przeciwnym razie, scipy.ndimage.convolve może go pokonać.

+0

Dziękuję Joe za szczegółową odpowiedź. Próbuję wykonać stacjonarną transformację falkową obrazu, która będzie używana do odszumiania. Właśnie tam chcę go użyć. – user1343318

+1

W takim przypadku 'scipy.ndimage.convolve1d', jak wspomniano w Bitwise, jest prawdopodobnie najlepszym wyborem. Jest zoptymalizowany pod kątem konkretnego przypadku użycia konwergencji tablicy 1d z macierzą 2d. Mam nadzieję, że pomaga! –

+1

Ponadto, jeśli nie chcesz wstawiać "A" za pomocą zer, lepszym rozwiązaniem może być "scipy.signal.convolve2d". Kształt zwróconej tablicy będzie domyślnie podobny do 'conv2' programu Matlab. (W początkowej fazie zapomniałem uwzględnić te informacje). Jeśli pracujesz z obrazem, zakładam, że chcesz, aby zwrócona tablica miała taki sam kształt jak oryginał. W takim przypadku 'ndimage' jest twoim najlepszym wyborem. –