Mustererkennung von Messreihen zur Positionierung

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 59 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    @Haudruferzappeltnoch Irgendwie habe ich das Gefühl, dass wir aneinander vorbei reden.
    Das lange Referenzarray wird stückweise mit einem Messarray verglichen.
    Die Stückelung ergibt sich aus dem Verhältnis beider Längen.
    Vorschlag:
    Ist das Referenzarray doppelt so lang wie das Messarray, werden 3 Vergleiche durchgeführt:
    vb-paradise.de/index.php/Attac…2e53e0e3c8852fd3362de6dac
    Rot: Referenzarray
    Schwarz: das Messarray, das an 3 Positionen des Referenzarrays angelegt wird.
    Bilder
    • Skizze.jpg

      18,66 kB, 762×251, 30 mal angesehen
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Nein, so habe ich es auch verstanden.
    Die Schleife aus Post 28 macht genau das, nur nicht an 3 Positionen, sondern an jeder Position des Referenzarrays, also 7499 mal. (Oder anders gesagt der Offset ist dort = 1)

    Auch bei 50% Überlappung wären solche Daten nicht gut abgedeckt:

    Also muss man für jeden! seiner Datentypen experimentell ermitteln, was denn eine gute Überlappung wäre, nur um den Schleifendurchlauf zu optimieren.

    Haudruferzappeltnoch schrieb:

    (Oder anders gesagt der Offset ist dort = 1)
    Weil jemand das Verfahren nicht verstanden hat.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Haudruferzappeltnoch Was Kreuzkorrelatzion eientlich macht bzw. aussagt?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die Fragestellung mit der ich hier eingestiegen bin war *eine Messdatenreihe auf eine Referenzmessreihe zu mappen*.
    Darauf hin war dein Vorschlag die Kreuzkorrelation, da geht man natürlich dann davon aus, dass die genau das macht.
    Der TE verwendet eine andere Korrelation, daraufhin sagst du das macht einen großen Unterschied. Daher habe ich mich für den Unterschied interessiert, weil auch die Korrelation des TE ja offensichtlich genau * tut.
    Ist das nachvollziehbar?

    Haudruferzappeltnoch schrieb:

    Ist das nachvollziehbar?
    Nicht ganz, dazu müsste ich beide Versionen gegeneinander testen, was ich jedoch nicht tun werde.
    In einem anderen Messdaten-Zusammenhang hat das einen Unterschied gemacht.
    ====
    Der TE hat leider nach Posten "seiner" Lösung die Kommunikation hier beendet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Du sollst nicht die Richtigkeit der Methode nachvollziehen, sondern meine vorangehenden Sätze.

    Der TE muss sich natürlich nicht damit auseinandersetzen.

    RodFromGermany schrieb:

    In einem anderen Messdaten-Zusammenhang hat das einen Unterschied gemacht.
    Das bedeutet für mich: Du kanst auch nicht den theoretischen Unterschied nennen, ob man nun die Differenz der Datenpunkte oder das Produkt der Datenpunkte berechnet. Oder den Unterschied, ob man nun 99% Überlappung oder 50% Überlappung verwendet. Sondern du hattest einen Spezialfall wo die Differenz mit 99% Überlappung ein falsches Ergebnis geliefert hat.

    So hab ich jetz wohl den Fall wo es andersrum ist.

    Haudruferzappeltnoch schrieb:

    Du kanst auch nicht den theoretischen Unterschied nennen
    Das nenne ich "Experimentelle Mathematik".
    Kreuzkorrelation ist aber immer die bessere Wahl, da ich einen Verlauf erhalte, den ich seinerseits auswerten kann.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Haudruferzappeltnoch schrieb:

    egal wie weit dieser vom Referenzwert abweichen mag
    Du hast die Kreeuzkorrelation offenbar noch nicht verstanden.
    Kreuz-korreliere mal einen Sinus mit einem Sinus und einem Cosinus gleicher Frequenz.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe ja gesagt die wikipedia seite kann ich nicht wirklich verstehen. Das hat sich seit post 15 nicht geändert.

    Du sagst prüfwert * refwert in Post 16. prüfwert * 0 gibt halt 0
    Da kann ich das mit egal welchen werten machen

    Wie wärs wenn du das mal "kreuzkorrelierst" ich hab das gefühl du denkst dir das aus

    Haudruferzappeltnoch schrieb:

    Du sagst prüfwert * refwert in Post 16. prüfwert * 0 gibt halt 0
    Das sind indizierte Summen von Produkten!
    Ich werd mal ein Beispiel machen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Der Code ist in C#, das dürfte kein Problem für Dich sein, den nach VB.NET zu übertragen.
    Der Plot ist das Resultat der hier verwendeten Werte.
    Sind beide Eingangsfelder identisch, spricht man von Autokorrelation.
    Spiele mit dem Array2, mach eine Phasenverschiebung (Werte vom Anfang ans Ende packen), gib andere Kurven vor.
    Und dann recherchiere, was die CCF aussagt.
    CrossCorrelation

    C#-Quellcode

    1. using System;
    2. using System.Text;
    3. namespace WindowsFormsApp1
    4. {
    5. static class CrossCorrelation
    6. {
    7. /// <summary>
    8. /// Struktur zur Übergabe von speziellen Werten
    9. /// bei der Berechnung der Kreuzkorrelation
    10. /// </summary>
    11. public struct CrossResult
    12. {
    13. /// <summary>das Ergebnisfeld</summary>
    14. public double[] Ccf;
    15. /// <summary>Koordinate des Maximums</summary>
    16. public int Index;
    17. /// <summary>das Maximum</summary>
    18. public double Maximum;
    19. public CrossResult(int length)
    20. {
    21. // Array zum Aufbau der CCF-Daten
    22. this.Ccf = new double[length];
    23. this.Index = 0;
    24. this.Maximum = double.MinValue;
    25. }
    26. public void FindMaximum()
    27. {
    28. this.Index = 0;
    29. this.Maximum = this.Ccf[0];
    30. int length = this.Ccf.Length;
    31. for (int i = 0; i < length; i++)
    32. {
    33. if (this.Maximum < this.Ccf[i])
    34. {
    35. this.Maximum = this.Ccf[i];
    36. this.Index = i;
    37. }
    38. }
    39. }
    40. public void Dump(string path)
    41. {
    42. StringBuilder sb = new StringBuilder();
    43. int length = this.Ccf.Length;
    44. for (int i = 0; i < length; i++)
    45. {
    46. sb.AppendLine($"{this.Ccf[i]}");
    47. }
    48. System.IO.File.WriteAllText(path, sb.ToString());
    49. }
    50. }
    51. /// <summary>
    52. /// Berechnung der diskreten Kreuzkorrelation zweier gleich langer Arrays
    53. /// </summary>
    54. /// <param name="one">Array 1 zur CCF</param>
    55. /// <param name="two">Array 2 zur CCF</param>
    56. /// <returns>spezielle Werte zum Array</returns>
    57. public static CrossResult CrossCorrelationLin(double[] one, double[] two)
    58. {
    59. if (one.Length != two.Length)
    60. {
    61. throw new ArgumentOutOfRangeException("two", "Not the same size");
    62. }
    63. int length = one.Length;
    64. CrossResult result = new CrossResult(length);
    65. for (int i1 = 0; i1 < length; i1++)
    66. {
    67. for (int i2 = 0; i2 < length; i2++)
    68. {
    69. // schnellste Methode, die korrekten Indizes zu berechnen
    70. result.Ccf[i2] += one[i1] * two[(length + i1 - i2) % length];
    71. }
    72. }
    73. result.FindMaximum();
    74. return result;
    75. }
    76. }
    77. }
    78. // ############################################################
    79. // Aufruf:
    80. private void Button1_Click(object sender, System.EventArgs e)
    81. {
    82. double[] a1 = new double[] { 1, 2, 3, 4, 5, 4, 3, 2, 1, 0 };
    83. double[] a2 = new double[] { 5, 4, 3, 2, 1, 0, 1, 2, 3, 4 };
    84. CrossCorrelation.CrossResult result1 = CrossCorrelation.CrossCorrelationLin(a1, a1);
    85. CrossCorrelation.CrossResult result2 = CrossCorrelation.CrossCorrelationLin(a1, a2);
    86. result1.Dump(@"D:\Temp\CorrelationAuto.txt");
    87. result2.Dump(@"D:\Temp\CorrelationCross.txt");
    88. }

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VB.NET-Quellcode

    1. int length = one.Length;
    2. CrossResult result = new CrossResult(length);
    3. for (int i1 = 0; i1 < length; i1++)
    4. {
    5. for (int i2 = 0; i2 < length; i2++)
    6. {
    7. // schnellste Methode, die korrekten Indizes zu berechnen
    8. result.Ccf[i2] += one[i1] * two[(length + i1 - i2) % length];
    9. }
    10. }
    11. result.FindMaximum();
    12. return result;

    Ob man erst durch i2 läuft oder erst durch i1 macht keinen Unterschied.

    VB.NET-Quellcode

    1. for (int i2 = 0; i2 < length; i2++)
    2. {
    3. for (int i1 = 0; i1 < length; i1++)
    4. {
    5. // schnellste Methode, die korrekten Indizes zu berechnen
    6. result.Ccf[i2] += one[i1] * two[(length + i1 - i2) % length];
    7. }
    8. }

    Ob + i2 oder - i2 ändert nur die Rotationsrichtung, ist also auch beliebig.

    VB.NET-Quellcode

    1. for (int i2 = 0; i2 < length; i2++)
    2. {
    3. for (int i1 = 0; i1 < length; i1++)
    4. {
    5. // schnellste Methode, die korrekten Indizes zu berechnen
    6. result.Ccf[i2] += one[i1] * two[(length + i1 + i2) % length];
    7. }
    8. }

    Dann ist es auch egal welches Array durchrotiert, also kann ich auch die Arrays vertauschen

    VB.NET-Quellcode

    1. for (int i2 = 0; i2 < length; i2++)
    2. {
    3. for (int i1 = 0; i1 < length; i1++)
    4. {
    5. // schnellste Methode, die korrekten Indizes zu berechnen
    6. result.Ccf[i2] += two[i1] * one[(length + i1 + i2) % length];
    7. }
    8. }

    Und length ist hier dein "Offset", den setzt du aber nicht hoch, zudem ist jetzt Offset = n, entgegen Post 29!
    Und das ist der Hauptpunkt hier, wenn der gleich bleibt, dann ergeben sich für length - i2 alle Werte, wie sie auch für i2 entstehen (0 bis 9), nur in anderer Reihenfolge.
    Oder anders ausgedrückt: x + length Mod length = x Mod length

    VB.NET-Quellcode

    1. for (int i2 = 0; i2 < length; i2++)
    2. {
    3. for (int i1 = 0; i1 < length; i1++)
    4. {
    5. // schnellste Methode, die korrekten Indizes zu berechnen
    6. result.Ccf[i2] += two[i1] * one[(i1 + i2) % length];
    7. }
    8. }

    Und das ist jetzt der Aufbau, den ich in Post 28 hatte

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Haudruferzappeltnoch schrieb:

    ändert nur die Rotationsrichtung, ist also auch beliebig.
    Nein.
    Das Maximum der CCF entspricht dem Index, bei dem beide Funktionen am besten matchen.

    Haudruferzappeltnoch schrieb:

    Und length ist hier dein "Offset"
    Nein.
    length ist die Länge der Arrays, hättest Du gewusst, wenn Du Dir den Code angesehen hättest.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe an der Maximum Funktion auch nichts geändert. Ich denke mal du schaust nicht auf den Code.

    Dann hast du gar kein Offset mehr wie du es in Post 29 vorschlägst, kommt trotzdem aufs selbe raus.

    Hab ich behauptet length ist nicht die Länge des Arrays???? Wat

    Die Schleifen sind äquivalent, darum gehts

    Haudruferzappeltnoch schrieb:

    Dann hast du gar kein Offset mehr wie du es in Post 29 vorschlägst, kommt trotzdem aufs selbe raus.
    Ich habe auch keine Referenzmessung mit viel mehr Punkten.
    Ich will zeigen, wie ein Problem gelöst werden kann, ich will das Problem nichtz lösen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Haudruferzappeltnoch Das haben wir doch bereits diekutiert: Mustererkennung von Messreihen zur Positionierung
    Dann muss natürlich noch ein wenig experimentelle Mathematik betrieben werden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!