Head Tracking Daten filtern/glätten
-
Hallo zusammen!
Ich habe momentan für eine 3d-Anwendung ein 6 DOF Head Tracking zur Änderung der Perspektive implementiert.
Mein Problem ist allerdings, dass das Tracking-System teilweise etwas zu sensibel Daten liefert. Wenn man still vor dem Display steht, "zittert" mein Bild teilweise, da anscheinend ein Wert (zB die Y-Koordinate des Translationsvektors) etwas hin und her-springt.
Also muss ich die Daten wohl irgendwie filtern, glätten.
Ich habe mal per google versucht generell dazu mal was rauszufinden, aber ich kann mir das bisher noch nicht wirklich vorstellen wie ich das implementieren kann.Ich muss ja anscheinend irgendwie "Zustände" (in meinem Fall die Daten die der Tracker liefert - rotationsmatrix, translationsvektor) speichern, und dazwischen interpolieren... ist meine Annahme richtig? Wie kann man sowas performant hinkriegen?
Ike
-
Wie wäre es, wenn man die Daten vom Tracker Fourier-transformiert und die hohen Frequenzen ausblendet? Sollte doch den Zweck erfüllen.
-
SeppJ schrieb:
Wie wäre es, wenn man die Daten vom Tracker Fourier-transformiert und die hohen Frequenzen ausblendet? Sollte doch den Zweck erfüllen.
Das hat bestenfalls Sinn, wenn die Störungen periodisch sind. Das wage ich aber mal zu bezweifeln.
Vielleicht hilft ein Median-Filter. Um genaueres sagen zu können, müsste man die genaue Art der Störung kennen.
-
Das hat bestenfalls Sinn, wenn die Störungen periodisch sind.
Nein, dazu muessen die Bewegungen nicht unbedingt periodisch sein. Die hochfrequenten nicht-periodischen Bewegungen werden ja gerade in "periodische" zerlegt. Alternativ koennte man auch einen gleitenden Durchschnitt oder so benutzen ... muss man halt testen ...
-
knivil schrieb:
Nein, dazu muessen die Bewegungen nicht unbedingt periodisch sein. Die hochfrequenten nicht-periodischen Bewegungen werden ja gerade in "periodische" zerlegt. Alternativ koennte man auch einen gleitenden Durchschnitt oder so benutzen ... muss man halt testen ...
Sorry, aber das ist totaler Quark. Eine Fourier Transformation zerlegt Dir ein Signal in seine einzelnen periodischen Bestandteile. Aperiodische Vorgänge lassen sich damit nicht erfassen. Wie soll was periodisch zerlegt werden, dass nicht periodisch ist?
Bei (reversiblen) Transformationen ändert sich ganz allgemein an den in einem Signal enthaltenen Informationen nichts. Du änderst nur die Art der Abbildung. Was vorher also nicht da war, ist auch nach der Transformation nicht da. Etwas das vorher zwar da, aber aufgrund der Abbildung nicht sichtbar war, kann sich nach einer Transformation offenbaren.[...]Die hochfrequenten nicht-periodischen Bewegungen[...]
Hochfrequent und nicht-periodisch passen irgendwie nicht zusammen.
-
Vielleicht reicht ja auch schon ein Schwellwert für den "Losreißimpuls". Bei Grafiktabletts gibt es manchmal eine solche Einstellungsmöglichkeit. Solange sich Bewegungen innerhalb eines kleinen Radius abspielen werden sie einfach ignoriert.
Ansonsten einfach mehrere Werte in einem Ringpuffer speichern und einen Filter drüberlegen. Am einfachsten wäre ein gleitendes Mittel. Ich bezweifle, dass Performance ein Problem ist, aber das Filtern wäre einfaches Multiplizieren und Addieren, dafür gibts sicher was auf modernen CPUs. Dann sind aber vielleicht größere Bewegungen etwas schwammig!
geloescht
-
Aperiodische Vorgänge lassen sich damit nicht erfassen. Wie soll was periodisch zerlegt werden, dass nicht periodisch ist?
@Tachyon: Sorry, aber das ist totaler Quark. Die Fouriertransformation stellt die Funktion als Linearkombination der Basisfunktionen { exp(iwt) } dar. Das ist vollstaendig, d.h. kann jede stetige Funktion beliebig genau approximieren. Das Spektrum sind meist die zugehoerigen Gewichtungen der Basisfunktionen, hier waere es wahrscheinlich kontinuierlich. D.h. es funktioniert fuer jede Funktion (naja, im Intervall beschraenkt sollte sie auch noch sein). Ich gehe hier von der kontinuierlichen Variante aus.
-
Als Hobby-DSPler, der sich mit solchen Themen über 10 Jahre beschäftigt hat, kann ich sagen, dass man natürlich alles mögliche (inklusive aperiodische Signale) Tiefpass-filtern kann.
Ein solches Glätten gabs damals zu Quake-Zeiten (dieses 3D Spiel von ID) auch schon für die Mäuse, die früher einfach eine schlechte räumliche und zeitliche Auflösung hatten. Das Glätten der Sensosordaten des 6-DOF-Trackers kann man prinzipiell genauso machen. Dafür braucht man auch keine FFT. Man kann dazu einen einfachen "BiQuad" nehmen:
#include <iostream> class biquad { float b0,b1,b2; // Filter Koeffizienten (Numerator) float a1,a2; // Filter Koeffizienten (Denominator) float t1,t2; // Zustand public: explicit biquad(float b0=1, float b1=0, float b2=0, float a1=0, float a2=0) : b0(b0),b1(b1),b2(b2),a1(a1),a2(a2),t1(0),t2(0) {} void set_filter(float b0=1, float b1=0, float b2=0, float a1=0, float a2=0) { this->b0 = b0; this->b1 = b1; this->b2 = b2; this->a1 = a1; this->a2 = a2; } void reset_state() { t1=0; t2=0; } float operator()(float x) { float t0 = x - a1*t1 - a2*t2; float retv = b0*t0 + b1*t1 + b2*t2; t2 = t1; t1 = t0; return retv; } }; int main() { // Koeffizienten fuer simplen 1st order Tiefpass-Filter biquad bqf (0.25f,0.25f,0,-0.5f,0); // Impulsantwort berechnen ... for (int i=0; i<20; ++i) { float in = (i==0); float out = bqf(in); std::cout << out << '\n'; } }
Wer mit anderen Koeffizienten experimentieren will, sollte mal auf der folgenden Seite nachgucken:
http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt.Was ist ein BiQuad? Ein BiQuad ist der kleinste Fitler-Baustein, mit dem man beliebige Filter zusammensetzten kann, indem man sie in Reihe schaltet. Die Koeffizienten werden bei komplexeren Filtern üblicherweise von Softwaretools berechnet, denen man nur sagt, was rauskommen soll (Amplituden/Phasen-Antwort). Für die Anwendung des OPs sollte ein Biquad ausreichen.
Gruß,
SP
-
Ike schrieb:
Ich muss ja anscheinend irgendwie "Zustände" (in meinem Fall die Daten die der Tracker liefert - rotationsmatrix, translationsvektor) speichern, und dazwischen interpolieren... ist meine Annahme richtig?
Bei Translation kannst Du eine Dämpfung schon recht einfach erzielen:
t_alt <-- t_alt + (t_neu-t_alt)*beta
wobei t_alt der gemerkte Vektor ist, den Du auch weiterverwendest und t_neu der Vektor ist, der vom Tracker kommt. Beta beeinflusst die Dämpfung. Beta=1 dämpft gar nicht. Bei Beta=0 wird sich dein t_alt nie ändern. Probier's einfach mal mit Werten dazwischen .... 0.5 oder 0.1 oder so.
Das mit der Rotationsmatrix ist komplizierter. Die besitzt ja eigentlich nur 3 Freiheitsgrade, obwohl Du in der Matrix 9 Elemente speicherst. Es ist aber möglich diese ähnlich zu filtern:
R_alt <-- R_alt * (R_alt^T * R_neu) ^ beta
Das mit der Matrix-Potenz ist hier gar nicht so wild. R_alt^T*R_neu =: Q ist ja auch eine 3D-Rotationsmatrix (orthogonal mit Determinante=1). Und für diese Matrizen kann man relativ leicht einen Vektor v (Rotations-Achse) der Länge 1 und einen Dreh-Winkel alpha bestimmten, sodass
Q = I + sin(alpha) T + (1-cos(alpha)) T^2
gilt, wobei I die 3x3 Einheitsmatrix und T eine von v abgeleitete 3x3 Matrix ist:
| 0 -v(1) v(2) |
| v(1) 0 -v(3) |
| -v(2) v(3) 0 |
ist.Die Potenz mit beta läuft dann einfach über den Drehwinkel:
Q^beta = I + sin(alpha*beta) T + (1-cos(alpha*beta)) T^2
Für die Bestimmug von v und alpha musst Du mal in'nem schlauen Buch nachschlagen. Da hab ich jetzt auch keinen Tipp parat. Viel Spass beim Implementieren.
Gruß,
SP
-
knivil schrieb:
Aperiodische Vorgänge lassen sich damit nicht erfassen. Wie soll was periodisch zerlegt werden, dass nicht periodisch ist?
@Tachyon: Sorry, aber das ist totaler Quark. Die Fouriertransformation stellt die Funktion als Linearkombination der Basisfunktionen { exp(iwt) } dar. Das ist vollstaendig, d.h. kann jede stetige Funktion beliebig genau approximieren. Das Spektrum sind meist die zugehoerigen Gewichtungen der Basisfunktionen, hier waere es wahrscheinlich kontinuierlich. D.h. es funktioniert fuer jede Funktion (naja, im Intervall beschraenkt sollte sie auch noch sein). Ich gehe hier von der kontinuierlichen Variante aus.
Natürlich kannst Du jedes kausale Signal in eine FT packen ohne das Informationen verloren gehen. Das habe ich oben bereits geschrieben. Ich habe jedoch die Sinnhaftigkeit zwecks Glättung angezweifelt.
Außerdem sagte ich, dass Du keine nützlichen Informationen für mehr oder weniger zufällige Ereignisse gewinnen kannst.
Natürlich kann man eine FFT benutzen um zu Filtern, aber das geht auch gut ohne FFT.
-
Sebastian Pizer schrieb:
[...]
Q = I + sin(alpha) T + (1-cos(alpha)) T^2
wobei I die 3x3 Einheitsmatrix und T eine von v abgeleitete 3x3 Matrix ist:
| 0 -v(1) v(2) |
| v(1) 0 -v(3) |
| -v(2) v(3) 0 |Mir ist gerade aufgefallen, dass die ja falsch ist. Ich hatte die Indizes 1 und 3 vertauscht. "v(1)" ist also die Z-Komponente der Rotationsachse, "v(2)" die Y-Komponente und "v(3)" die X-Komponente. Jedenfalls findet man schnell etwas, wenn man eine Suchmaschine danach fragt, wie man Rotationsmatrix in Achse+Winkel umrechnet und zurück. Mit "Quaternions" kann man es auch noch probieren. Das ist im Prinzip das gleiche ("Achse+Winkel"). Aber ich habe die nie so richtig verstanden, die Biester.
Gruß,
SP