Implementierung eines Low pass Filters

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich würde etwas benutzen , das funktioniert. Das habe ich sich schon mal gesagt. Der MA sah laut deiner Aussage besser aus. Dann würde ich den nehmen. Willst du aber partout nicht.

Ich habe deine Daten nicht vorliegen, und kann darum den BW auch nicht beurteilen, und wie man den besser einstellt.


Persönlich würde auch überhaupt nicht so segmentieren, wir du das hier skizzierst. Sondern den Filter nur gegen den Noise einsetzen (die IMUs produzieren davon eine Menge, aber der ist relativ hochfrequent vs deinem Curling/den eigentlichen Bewegungen), und mit einer Peak detection arbeiten. Denn dein ganzer Ansatz ist in meinen Augen sinnlos, wenn man zu Beginn seine curls mit 1s erledigt, aber gegen Ende des Sets 1.5s braucht. Dann ist die Grundfrequenz natürlich komplett anders, und damit tritt die Chimäre “saubere Sinuswelle” auch nicht zu Tage. Aber von bottom Peak zu Top Peak kann man sich immer noch hangeln. Die Peak Detection würde ich über eine lokales Suchfenster erledigen. Oder ggf. nach anderen Algorithmen suchen. Und dann muss man von Peak zu Peak extrahieren, und die Daten auf einen immer gleich langen Feature Vector resamplen. ZB bicubisch.
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Danke für die Erklärung zur Segmentierung. Ich möchte dahin kommen zu diesem Schritt.
Ich wollte auch segmentieren in dem ich Peaks finde. Ich dachte nur bei einer veranschaulichen Graphen wäre es einfacher die Peaks zu finden, da die Daten geglätteter sind.

Jetzt wäre es ja denke ich sehr mühsam Peaks zu finden da sie nicht gut gefiltert sind oder?

Was wäre ein Ansatz den BW besser einzustellen. Es reicht nicht nur an den Parametern rumzuspielen denke ich oder?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe nicht, dass es mühsamer ist, die peaks zu finden, auch wenn da höher frequente Anteile drin sind. Und je mehr Frequenzen ausgefiltert sind, desto weniger genau ist der Peak.

Und außer den Parametern hat der BW doch nichts, was man einstellen kann. Also muss du an denen drehen.
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Ich dachte es sei mühsamer Peaks zu finden, da es viel mehr lokale Peaks gibt, da sie nicht so gut gefiltert sind wie jetzt wegen den Zacken.

Die Parameter müssten aber für alle Daten gleich sein. Heißt wenn ich eine Einstellung finden sollte wo beispielsweise der Cutoff bei 5.5 und order bei 3 liegt und es passt, darf man die Parameter für die nächste Datenreihe sprich Bizepcurls nicht mehr verändern und müssen für alle Bizepcurls gültig sein oder?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da dein Modell unter diesen Annahmen trainiert wurde, müssen die gleich bleiben.
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Ah okay danke.Wenn ich keinr Einstellung finden wo die Daten besser aussehen und ich jetzt so segmentieren würde, hat das filtern ja kaum was gebracht oder?
Weil die Daten im Grunde genommen gleich aussehen.

Oder würdest du sie dennoch segmentieren und die sample rate muss ja bei 100 bleiben oder?
Heißt ich kann nur am order und Cutoff schrauben
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das segmentieren muss doch für das Training eh passieren. Du kannst doch nur einen definierten curl klassifizieren. Nicht eine letztlich beliebige Menge.

Warum der Filter so komisch ist - kA. Wie gesagt, ich kann den nicht ausprobieren. An sich sollte schon mit Ordnung 1 und zb 10Hz cutoff eine deutliche Glättung rauskommen. Warum nicht, kann ich nicht sagen. Musst du ausprobieren. Oder eben - zum tausendsten mal - den MA bemühen. Denn am Ende zählt das Ergebnis. Wenn du deinem Prof nix funktionierendes vorlegen kannst, aber den BW drin hast, ist das weniger wert, als ein funktionierendes System, das nicht den vorgeschlagenen Filter implementiert.
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Da hast du recht, jedoch würde ich gerne alles versucht haben bevor ich den MA nutzen.

Irgendwie filtert es bei keinem Cutoff, was ich probiert habe.
Ich teile mal den Link meiner Daten, vielleicht übersehe ich was. Ich arbeite mit der Euklidischen Norm und diese die Spalte mit der Euklidischen Norm soll gefiltert werden, so kann ich die einzelnen Achsen x,y,z ignorieren.

https://www.dropbox.com/s/fty5wootuyme3 ... a.csv?dl=0
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Welche zeitliche Auslösung ist denn das? 10s pro Schritt sind es ja nicht, oder?
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Es sind dann 0,01 sekunden, beim formatieren der Daten vom IMU sind die Kommas verschwunden. Weil da mit Punkte statt mit Kommas getrennt wird, wenn man die CSV-Datei exportiert. Da habe ich dann erstmal die formartiert.

Theoretisch müsste man zeitliche Auflösung durch 1000 teilen, um das original zu bekommen.
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Ich habe die Originaldatei unverarbeitet hochgeladen, damit du siehst was ich genau meine. Hier sind die zahlen nach der 0 mit einem Komma mit einem Punkt getrennt. Vielleicht liegt hier schon ein Fehler von mir und du hast vielleicht eine besser Übersicht.

https://www.dropbox.com/s/roz4iwjeihc8e ... 2.csv?dl=0
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das problem ist simpel: deine Daten sind so Niederfrequent, dass die Grenzfrequenz richtig niedrig sein muss. So sieht das bei mir zb mit 1Hz aus:

https://www.dropbox.com/s/8aet9588wl76v ... 3.PNG?dl=0

Der Code ist hier, ich habe auf meinem iPad kein SciPy. Also per Hand nach https://www.meme.net.au/butterworth.html entwickelt.

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt
 
# BW 20Hz cutoff at 100Hz samplerate
# 2.376⋅yi = (1⋅xi + 1⋅xi-1) + 0.376⋅yi-1

class BW:
    
    def __init__(self, a, b):
        self._a = a
        self._b = b
        self._xn_1 = None
        self._yn_1 = 0
        
    def __call__(self, x):
        if self._xn_1 is None:
            self._xn_1 = x
            
        y = self._yn_1 = ((x + self._xn_1) + self._a * self._yn_1) / self._b
        self._xn_1 = x
        return y
            
# 5Hz
filter = BW(5.376, 7.376)
# 1Hz
filter = BW(30.821, 32.821)
filter = np.vectorize(filter)

sensor_data = []
with open('samplesdata.csv') as inf:
    next(inf) # skip header
    for i, line in enumerate(inf, start=2):
        if line.strip():
            v = float(line.strip().split(';')[-1].replace(',', '.'))
            sensor_data.append(v)
            
sensor_data=np.array(sensor_data)
  

filtered_data = filter(sensor_data)

plt.figure()
plt.subplot(211)
plt.plot(sensor_data, color='green')
plt.grid(color='green', linestyle='--', linewidth=0.5)
plt.title('original signal')
 
plt.subplot(212)
plt.plot(filtered_data, color='red')
plt.title('Filtered')
plt.grid(color='green', linestyle='--', linewidth=0.5)
plt.show()
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Das sieht super aus! Genau das ist es was ich haben wollte. Was müsste ich an meinem Code ändern, damit das Ergebnis rauskommt?

Ich habe den cutoff auf 1 gestellt, aber es ändert sich nicht.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Keine Ahnung. Ich kann das nicht benutzen, also auch nicht fixen. Ich habe doch code gezeigt, der tut. Gibt’s nen Grund den nicht zu benutzen?
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Ne alles gut, ich will es nur fürs Verständnis wissen. Ich sehe bei dir sample rate nicht, wo ist sie auf 100 Hz eingestellt, dazu wo ist der Cutoff bei 20 Hz eingestellt?

Und ich verstehe die vektorisierten Parameter nicht. Wie hast du die Zahlen ermittelt und wozu sind sie da?
Benutzeravatar
Dennis89
User
Beiträge: 1153
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

schau dir noch mal den Link von @__deets__ an. Da kann man doch Werte einstellen, dann siehe die Kommentare in seinem Code unter den Importen und dann kommst du normalerweise darauf, wie der Filter für 5Hz oder 1Hz im Code einzustellen ist.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Guten Morgen,
bei dem Link ist der cutoff auf 20 Hz und die sample rate auf 100 Hz.

Die Formel lautet: 4.841⋅yi = (1⋅xi + 2⋅xi-1 + 1⋅xi-2) + 1.789⋅yi-1 + -0.948⋅yi-2

Aber im Kommentar steht 2.376⋅yi = (1⋅xi + 1⋅xi-1) + 0.376⋅yi-1

Wenn ich den auf 1 Hz einstellle kommt raus: 1058.546⋅yi = (1⋅xi + 2⋅xi-1 + 1⋅xi-2) + 2023.090⋅yi-1 + -968.544⋅yi-2
Bei 5 Hz: 49.792⋅yi = (1⋅xi + 2⋅xi-1 + 1⋅xi-2) + 77.727⋅yi-1 + -31.934⋅yi-2

Ich sehe auch nicht wie auf die vektorisierten Parameter geschlossen wird.

Ich habe wahrscheinlich einen Denkfehler oder?
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe nur eine Filter erster Ordnung genommen. Dann hat man nur zwei Koeffizienten und zwei Tabs.
__deets__
User
Beiträge: 14529
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe noch eine deutliche Verbesserung gefunden - das anfangswert-Problem anders gelöst:

Code: Alles auswählen

class BW:
    
    def __init__(self, a, b):
        self._a = a
        self._b = b
        self._xn_1 = None
        self._yn_1 = 0
        
    def __call__(self, x):
        if self._xn_1 is None:
            self._xn_1 = x
            self._yn_1 = x
        y = self._yn_1 = ((x + self._xn_1) + self._a * self._yn_1) / self._b
        self._xn_1 = x
        return y
Damit sind die Amplituden deutlich korrekter. Es ist ein bisschen seltsam, dass das BW Ding aus scipy nicht tut 🤔
Risingsun
User
Beiträge: 43
Registriert: Dienstag 8. November 2022, 14:56

Ah okay nur zum Vertständnis. Also stellen die Vektorisierten Parameter, die Koeffizienten dar der ersten Ordnung?
Und bei dem Link ist der Filter nicht in erster Ordnung, wie hast du es umgerechnet?
Antworten