2014-07-05 11 views
6

Hallo Python-Enthusiasten!SciPy medfilt falsches Ergebnis

Ich arbeite derzeit mit Signalfilterung für Forschungszwecke und entschied mich, SciPy zu verwenden. Nichts besonderes, nur Automatisierung der Routinearbeit.

So, hier ist der Code

from scipy.signal import medfilt 
print(medfilt([2,6,5,4,0,3,5,7,9,2,0,1], 5)) 

Aber die Sache ist, dass zurück sequense falsch berechnet

SciPy: [ 2. 4. 4. 4. 4. 4. 5. 5. 5. 2. 1. 0.] 
Me : [ 5. 4.5 4. 4. 4. 4. 5. 5. 5. 2. 1.5 1.] 

Es scheint zu sein, dass die Entwickler von Paket ein Detail durcheinander. Wenn die Apertur (Kernel in SciPy) größer ist als das zu analysierende Fenster, gibt es eine weitere Filterregel.

Zum Beispiel mit kernel=5 gefilterte Teilfolge von [2, 6, 5] hat Median 5 und nicht 2 als SciPy berechnet, nicht wahr? Und in gleicher Weise, wenn kernel=5 für Subsequenz [2,6,5,4] Mediane 5 und 4 sind, müssen wir Durchschnitt zwischen ihnen nehmen, so ist der Median 4,5.

Kann mir jemand erklären, wer in diesem Fall das richtige Ergebnis hat?

Antwort

13

Ich glaube, dass sowohl Sie als auch SciPy korrekte Ergebnisse haben. Der Unterschied liegt darin, was an den Grenzen passiert, aber ich glaube, dass sowohl Sie als auch SciPy gültige Entscheidungen getroffen haben.

Die Frage ist was passieren sollte, wenn Ihr Schiebefenster an den Rändern ist, und es keine gültigen Daten gibt, um Ihr Schiebefenster zu füllen.

Sie haben den Medianwert des gültigen Teils des gleitenden Fensters gewählt. Dies ist sinnvoll, kann jedoch zu Verzerrungen führen, da Ihre Kantenpunkte im Vergleich zu allen anderen Punkten überrepräsentiert sind.

SciPy entschied sich stattdessen, das Signal an jeder Kante durch Auffüllen von Nullen zu erweitern. Also, an den Grenzen, SciPy im Wesentlichen der Berechnung

>>> np.median([0, 0, 2, 6, 5]) 
2.0 
>>> np.median([0, 2, 6, 5, 4]) 
4.0 
>>> np.median([9, 2, 0, 1, 0]) 
1.0 
>>> np.median([2, 0, 1, 0, 0]) 
0.0 

Der Grund, warum SciPy tut dies ist fast definitiv Geschwindigkeit bezogen werden: es über viele Male für das gleiche tun optimiert ist, und es ist viel einfacher zu optimieren median für eine ganze Reihe von 5-Element-Arrays, als es für eine ganze Reihe von 5-Element-Arrays zu optimieren, und auch zwei 4-Element-Arrays und zwei 3-Element-Arrays. Es ist definitiv ein Argument zu machen, dass es nicht mit Nullen aufgefüllt werden sollte, sondern mit den Grenzwerten, aber es sollte angemerkt werden, dass keine Grenzstrategie perfekt sein wird; Der ideale Weg, um mit Grenzproblemen umzugehen, hängt von Ihrem speziellen Signal ab.

Wenn Sie Wikipedia's description of median filters sehen, erweitern sie das Signal an jeder Kante, indem Sie es mit dem Wert an den Kanten auffüllen, was ebenfalls sinnvoll erscheint. Sie beachten auch diese drei anderen Möglichkeiten, mit Grenzproblemen umzugehen:

  • Vermeiden Sie die Verarbeitung der Grenzen, mit oder ohne die Signalgrenze danach beschneiden.
  • Abrufen von Einträgen von anderen Stellen im Signal. Bei Bildern können beispielsweise Einträge von der fernen horizontalen oder vertikalen Grenze ausgewählt werden.
  • Schrumpfen Sie das Fenster in der Nähe der Grenzen, so dass jedes Fenster voll ist (wie Sie es getan haben.)
  • Am Ende müssen Sie wirklich verschiedene Optionen ausprobieren und sehen, was am besten für Ihr Signal funktioniert. Eine Kernannahme dieser Art von Filterung ist, dass Ihr Signal ziemlich groß wird und das Grenzproblem niemals so kritisch sein sollte (da der Großteil des Signals nicht an der Grenze existiert). Es wäre schön, wenn SciPy dir erlauben würde zu wählen, was es an den Grenzen tun soll!

    +0

    einfach ein wenig zu dieser Antwort zu erweitern, die für alternative Roll medianen Funktionen sucht, kann in aussehen: Pandas rollen Median: http://pandas.pydata.org/pandas-docs/stable/computation.html# Moving-Rolling-Statistik-Momente und scipy.ndimage: http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.ndimage.filters.median_filter.html – ConnectedSystems