2017-01-25 3 views
1

Ich möchte 2D-Faltung auf Bildern der Größe 600 X 400 mit einem 10 X 10 Filter durchführen. Der Filter ist nicht trennbar. scipy.signal.convolve2d funktioniert derzeit gut für mich, aber ich erwarte bald viel größere Bilder.Scipy convolve2d mit Subsampling wie Theano conv2d?

dass Um dem entgegenzuwirken, ich habe zwei Ideen

  1. Größe der Bilder
  2. Subsampling (oder schreitend)?

Die Konzentration auf die Unterabtastungs Teil hat Theanos eine Funktion, die Faltung auf die gleiche Weise wie scipy convolve2d der Fall ist, sehen theano conv2d

Es ist auch zu den Unterabtastungs Option hat. Aber die Installation von theano auf Windows war schmerzhaft für mich. Wie bekomme ich Subsampling Arbeit mit scipy.signal.convolve2d? Irgendwelche anderen Alternativen (das erfordert nicht, dass ich mir eine schwergewichtige Bibliothek installiere)?

+1

Ist Ihr Filter gehen mit den Bildern wachsen? In diesem Fall können Sie versuchen, in [fftconovolve] (https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.fftconvolve.html) zu suchen, da IIRC im Gegensatz zu vielen anderen numerischen Computing-Software scipy doesn ' t verwenden fft standardmäßig. Wenn dein Filter bei 10x10 bleibt, wird dir das natürlich nicht viel bringen. –

+0

Mein Filter bleibt gleich. Ich habe mich tatsächlich bewegt. Und es ist in der Tat schnell (2X für meine Zwecke). Es hat aber auch keine Subsampling-Option – GKS

+0

Ich habe etwas Code zu der A. Nur 1d habe ich Angst, sollte aber einfach zu verallgemeinern sein. Guck mal. –

Antwort

1

Sie können Subsampling von Hand implementieren, ich werde nur 1d zur Vereinfachung skizzieren. Angenommen, Sie möchten s = d * f auf einem regulären Untergitter mit dem Abstand k abtasten. Dann ist Ihr n-tes Beispiel s_nk = sum_i = 0^10 f_i d_nk-i. Zu beachten ist hier, dass die Indizes von f und d immer zu einem Vielfachen von k summieren. Dies legt nahe, es in Untersummen aufzuteilen s_nk = sum_j = 0^k-1 sum_i = 0^10/kf_j + ik d_-j + (n-i) k. Was Sie also tun müssen, ist: Unterabtastung von d und f in Gittern mit dem Abstand k bei allen Offsets 0, ..., k-1. Convolve alle Paare von unterabgetasteten d und f, deren Offsets Summe auf 0 oder k und addieren Sie die Ergebnisse.

Hier ist ein Code für 1d. Sie implementiert grob das oben Genannte, nur die Gitter sind etwas anders platziert, um die Indexverwaltung zu erleichtern. Die zweite Funktion macht es auf dumme Weise, d.h. berechnet die volle Faltung und dezimiert dann. Es ist zum Testen der ersten Funktion gegen.

import numpy as np 
from scipy import signal 

def ss_conv(d1, d2, decimate): 
    n = (len(d1) + len(d2) - 1) // decimate 
    out = np.zeros((n,)) 
    for i in range(decimate): 
     d1d = d1[i::decimate] 
     d2d = d2[decimate-i-1::decimate] 
     cv = signal.convolve(d1d, d2d, 'full') 
     out[:len(cv)] += cv 
    return out 

def conv_ss(d1, d2, decimate): 
    return signal.convolve(d1, d2, 'full')[decimate-1::decimate] 

Edit: 2d Version:

import numpy as np 
from scipy import signal 

def ss_conv_2d(d1, d2, decy, decx): 
    ny = (d1.shape[0] + d2.shape[0] - 1) // decy 
    nx = (d1.shape[1] + d2.shape[1] - 1) // decx 
    out = np.zeros((ny, nx)) 
    for i in range(decy): 
     for j in range(decx): 
      d1d = d1[i::decy, j::decx] 
      d2d = d2[decy-i-1::decy, decx-j-1::decx] 
      cv = signal.convolve2d(d1d, d2d, 'full') 
      out[:cv.shape[0], :cv.shape[1]] += cv 
    return out 

def conv_ss_2d(d1, d2, decy, decx): 
    return signal.convolve2d(d1, d2, 'full')[decy-1::decy, decx-1::decx] 
+0

Das ist interessant. Lass mich das ausprobieren. Ich bin immer noch nicht sicher, ob ich die 2D-Version funktioniert – GKS

+0

Ok, das habe ich einmal für Sie getan, siehe aktualisierte A. –

+0

Danke Paul für die Antwort. Ich habe tatsächlich die 2D-Funktion, aber deine ist etwas schneller. Ich werde dies akzeptiert – GKS