myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Rund um die Programmierung » Algorithmus um Kurve (eine Liste von Punkten) zu komprimieren
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Algorithmus um Kurve (eine Liste von Punkten) zu komprimieren

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien


michlG ist offline

Algorithmus um Kurve (eine Liste von Punkten) zu komprimieren

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo zusammen,

ich habe momentan ein ziemlich nerviges Problem.
Vor einiger Zeit habe ich ein kleines Benutzersteuerelement geschrieben dass verschiedene Funktionen bereitstellt um Daten in einem Chart darzustellen.

Klappt auch ganz gut, aber jetzt beklagten sich die Benutzer über eine angeblich schlechte Performance.
Der Grund dafür ist dass pro Linie bis zu 15.000 Punkte übergeben wurden.
Und bei 20 Linien kommt man damit auf 300.000 Punkte was natürlich das Charting-Control etwas überlastet ;-)

Ich suche also einen Algorithmus der mir die 15.000 Punkte (immer DateTime mit double Paar) auf 1000 Punkte zusammenfasst.
Dabei sollte aber noch die grobe Grundstruktur der Linie erhalten bleiben.

Mittlerweile habe ich schon einiges versucht, aber der Mathematiker in mir will nicht wirklich aufkommen.
z.B: hab ich einfach immer X Punkte zu einem zusammengefasst indem ich den Mittelwert genommen habe.
Das war danach auch schön schnell aber die Linien wurden extrem verfälscht.
Zudem hab ich versucht den Min/Max-wert von den einzelnen Bereichen zu behalten und dann vom Rest den Mittelwert zu bilden -> resultat: gleich schlimm wie beim normalen Durchschnitt.

Kennt evtl. jemand einen Algorithmus mit dem die Linie nicht so extrem verfälscht werden würde?
Details sollen verschwinden aber die Grundstruktur sollte erkennbar bleiben :)

Vielen Dank im Voraus

Gruss
Michael

Hier noch ein kleines Beispielbild. Oben die Unkomprimierte Version und unten die Komprimierte Version. Wie man sieht erkennt man fast nicht dass es sich um die selben Daten handelt. Es handelt sich um Werte einer Maschine und ab und an gibt es da größere Abweichungen welche man oben aufgrund der vielen Punkte nicht sieht. Unten jedoch sind die gut sichtbar.
Kurz gesagt soll es ähnlich ausschauen wie oben aber mit viel weniger Punkten :)

michlG hat dieses Bild (verkleinerte Version) angehängt:
Beispiel.png
Volle Bildgröße

30.07.2010 18:40 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
gfoidl gfoidl ist männlich
myCSharp.de-Team

avatar-2894.jpg


Dabei seit: 07.06.2009
Beiträge: 6.659
Entwicklungsumgebung: VS 2019
Herkunft: Waidring


gfoidl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ev. wäre eine Medianfilterung (ein Rangordnungsfilter) passend. Über die Filterlänge kann eingestellt werden wie fein oder grob. Wenn eine lokale Störung von n Abtastwerten ausgefiltert werden soll muss der Filter 2n+1 lang sein.

Edit: Filtern alleine behält natürlich die Anzahl der Werte bei*. Daher auch ein Ersetzen der Werte im Fenster des Filters durch den Ausgabewert des Filters um eine Reduktion zu erreichen.

* In nachstehender Impl. wird dies erreicht indem die Anfangswerte gespiegelt werden.
Für den Medianfilter verwende ich folgende (nicht optimierte) Version:

C#-Code (Medianfilter):
using System;
using System.Collections.Generic;
using System.Linq;

namespace gfoidl.Signalprocessing.Filter.NonLinear
{
    /// <summary>
    /// Stellt einen Median-Filter dar.
    /// </summary>
    /// <remarks>
    /// Median-Filter sind eine gute Wahl zum Ausfiltern von Ausreißern (auch
    /// Spikes genannt).
    /// <para>
    /// Für das Ausfiltern einer Störung von n Abtastwerten der Stichprobe
    /// muss die Filterlänge 2n+1 sein.
    /// </para>
    /// </remarks>
    /// <seealso cref="MovingAverageFilter"/>
    public class MedianFilter : NonLinearFilter
    {
        /// <summary>
        /// Erstellt eine Instanz eines Median-Filters.
        /// </summary>
        /// <param name="filterLength">
        /// Die Filterlänge. Es muss eine ungerade Zahl übergeben werden.
        /// </param>
        /// <exception cref="ArgumentException">
        /// <paramref name="filterLength"/> ist keine ungerade Zahl oder
        /// ist &lt; 3
        /// </exception>
        public MedianFilter(int filterLength) : base(filterLength) { }
        //---------------------------------------------------------------------
        /// <summary>
        /// Die Strategie mit der die Daten gefiltert werden sollen.
        /// </summary>
        /// <param name="sequence">
        /// Die Daten welche vom Filterfenster erfasst sind.
        /// </param>
        /// <returns>Den gefilterten Wert.</returns>
        protected override double FilterOperation(IEnumerable<double> sequence)
        {
            List<double> sort = sequence.ToList();
            sort.Sort();
            int n = sort.Count;

            if (n % 2 == 0)
                return (sort[n / 2 - 1] + sort[n / 2]) * 0.5;
            else
                return sort[(n - 1) / 2];
        }
    }
}

C#-Code (Basisklasse für nichtlineare Filter):
using System;
using System.Collections.Generic;
using System.Linq;

namespace gfoidl.Signalprocessing.Filter.NonLinear
{
    /// <summary>
    /// Stellt die Basisimplementierung eines nichtlinearen Filters
    /// bereit.
    /// </summary>
    /// <remarks>
    /// Nichtlineare Filter schließen die Gruppe der Rangordnungsfilter ein.
    /// </remarks>
    public abstract class NonLinearFilter : IFilter
    {
        /// <summary>
        /// Die Filterlänge.
        /// </summary>
        public int FilterLength { get; private set; }
        //---------------------------------------------------------------------
        /// <summary>
        /// Erstellt eine Instanz des nichtlinearen Filters.
        /// </summary>
        /// <param name="filterLength">
        /// Die Filterlänge. Es muss eine ungerade Zahl übergeben werden.
        /// </param>
        /// <exception cref="ArgumentException">
        /// <paramref name="filterLength"/> ist keine ungerade Zahl oder
        /// ist &lt; 3
        /// </exception>
        protected NonLinearFilter(int filterLength)
        {
            if (filterLength % 2 == 0)
                throw ExceptionHelper.Argument(
                    () => filterLength,
                    "Der Wert muss eine ungerade Zahl sein.");

            if (filterLength < 3)
                throw ExceptionHelper.Argument(
                    () => filterLength,
                    "Der Wert muss größer als 3 sein.");
            //-----------------------------------------------------------------
            this.FilterLength = filterLength;
        }
        //---------------------------------------------------------------------
        /// <summary>
        /// Filtert die Werte.
        /// </summary>
        /// <param name="values">Die zu filternden Werte.</param>
        /// <returns>Gefilterte Werte.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="values"/> ist <c>null</c>.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="values"/> ist <c>null</c>, eine leere Menge oder
        /// die Anzahl der Elemente kleiner als die Filterlänge.
        /// </exception>
        /// <remarks>
        /// Der Filter spiegelt die Anfangs- und Endwerte so dass die Anzahl
        /// der Elemente in der Stichprobe erhalten bleibt. Üblicherweise würde
        /// bei Filtern die Anzahl N-(Filterlänge-1) betragen. Das ist hier
        /// aufgrund des ausgeklügelten Spiegelverfahrens nicht der Fall.
        /// </remarks>
        public IEnumerable<double> Filter(IEnumerable<double> values)
        {
            if (values == null)
                throw ExceptionHelper.ArgumentNull(() => values);

            int n = values.Count();

            if (n == 0)
                throw ExceptionHelper.NoElements(() => values);

            if (n < this.FilterLength)
                throw ExceptionHelper.Argument(
                    () => values,
                    "Die Anzahl der Elemente darf nicht kleiner als die " +
                    "Filterlänge sein.");
            //-----------------------------------------------------------------
            // Offset aus der Filterlänge berechnen:
            int offset = (this.FilterLength - 1) / 2;

            // Tipp: Aufzeichnen um die Indextransformation besser zu
            // verstehen.
            // +---+---+---+---+---+---+----
            // | 0 | 1 | 2 | 3 | 4 | 5 | ...
            // +---+---+---+---+---+---+----
            // Da der Filter symmetrisch zum betrachteten Abtastpunkt ist
            // müssen die ersten Werte der Stichprobe gesondert behandelt
            // werden. Hier werden so viele Folgewerte am Abtastpunkt
            // gespiegelt so dass sich ein volles Fenster ergibt. Der Median
            // sortiert die Werte -> dies erleichtert die Auswahl der Elemente
            // denn es muss keine Rücksicht auf die Ordnung genommen werden.
            // Die Werte ungefiltert zurückgeben ist nicht sinnvoll denn
            // es könnte ja der erste Punkt bereits ein Spike sein.
            for (int i = 0; i < offset; i++)
            {
                // Sequenz mit aktuellem Element + Folgeelementen:
                var q1 = values.Skip(i).Take(offset + 1);

                // Werte vor dem aktuellen Element (sofern vorhanden):
                var q2 = values.Take(i);

                // Werte die gespiegelt werden:
                var q3 = values.Skip(i + 1).Take(offset - i);

                // Filterung:
                yield return FilterOperation(q1.Concat(q2).Concat(q3));
            }

            // Über alle Werte der Stichprobe iterieren. Die Daten welche
            // vom Filterfenster erfasst werden werden dann symmetrisch
            // zum betrachteten Abtastpunkt ausgewählt. Daher muss bei der
            // oberen Schranke die Filterlänge berücksichtigt werden.
            // Der Median sortiert die Daten -> daher muss keine Rücksicht
            // auf die Ordnung der Elemente während der Auswahl getroffen
            // werden. Wichtig ist nur dass alle Elemente im Filterfenster
            // ausgewählt werden.
            for (int i = 0; i < n - this.FilterLength + 1; i++)
                yield return FilterOperation(values
                    .Skip(i)
                    .Take(this.FilterLength));

            // Wie die Startwerte müssen die letzten Werte gesondert behandelt
            // werden. Es werden alle möglichen Werte genommen und dann
            // wird das Fenster mit den gespiegelten Werten vor dem aktuellen
            // Abtastpunkt aufgefüllt.
            for (int i = values.Count() - offset; i < values.Count(); i++)
            {
                // Sequenz mit dem aktuellen Element + Vorherelemente:
                var q1 = values.Skip(i - offset).Take(offset + 1);

                // Werte nach dem aktuellen Element (sofern vorhanden):
                var q2 = values.Skip(i + 1).Take(values.Count() - i - 1);

                // Werte die gespiegelt werden:
                int remaining = this.FilterLength - q1.Count() - q2.Count();
                var q3 = values.Skip(i - remaining).Take(remaining);

                // Filterung:
                yield return FilterOperation(q1.Concat(q2).Concat(q3));
            }
        }
        //---------------------------------------------------------------------
        /// <summary>
        /// Die Strategie mit der die Daten gefiltert werden sollen.
        /// </summary>
        /// <param name="sequence">
        /// Die Daten welche vom Filterfenster erfasst sind.
        /// </param>
        /// <returns>Den gefilterten Wert.</returns>
        protected abstract double FilterOperation(IEnumerable<double> sequence);
    }
}

mfG Gü

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von gfoidl am 30.07.2010 19:37.

30.07.2010 18:52 Beiträge des Benutzers | zu Buddylist hinzufügen
Corpsegrinder
myCSharp.de-Mitglied

Dabei seit: 30.01.2007
Beiträge: 401
Entwicklungsumgebung: VS 2008 , .Net 3.5


Corpsegrinder ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Versuch doch einfach die Punkte genau dann zusammenzufassen, wenn viele Aufeinanderfolgende einen ähnlichen Wert haben, dann verhinderst du die grobe Verfälschung, sondern hast nur noch eine minimale Abweichung des urspünglichen Graphen.
30.07.2010 19:13 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
MarsStein MarsStein ist männlich
myCSharp.de-Poweruser/ Experte

avatar-3191.gif


Dabei seit: 27.06.2006
Beiträge: 3.156
Entwicklungsumgebung: VS 2013, MonoDevelop
Herkunft: Trier -> München


MarsStein ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Zitat:
... pro Linie bis zu 15.000 Punkte übergeben wurden.

über welchen Zeitraum erstrecken sich denn die 15000 Werte?
Ich meine , stellt das Bild das komplette Control dar, oder erstreckt sich das noch (viel) weiter nach rechts?

Denn das Bild hat in er Breite ja mal gerade 786px, das heisst auf jeden Pixel würden etliche Punkte gezeichnet, die gehen ja schon allein durch die Auflösung flöten.

Es dürfte ja nicht allzu schwierig sein zu ermitteln, welche Punkte ohnehin auf den selben Pixel der Zeitachse fallen.
Vielleicht reicht es ja, diese Werte zu mitteln und dann wirklich nur für jeden tatsächlich vorhandenen Pixel auf der Zeitachse diesen Mittelwert darzustellen.

Gruß, MarsStein
30.07.2010 19:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
VizOne VizOne ist männlich
myCSharp.de-Mitglied

avatar-1563.gif


Dabei seit: 26.05.2004
Beiträge: 1.373
Entwicklungsumgebung: VS 2010


VizOne ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von michlG:
Hier noch ein kleines Beispielbild. Oben die Unkomprimierte Version und unten die Komprimierte Version. Wie man sieht erkennt man fast nicht dass es sich um die selben Daten handelt. Es handelt sich um Werte einer Maschine und ab und an gibt es da größere Abweichungen welche man oben aufgrund der vielen Punkte nicht sieht. Unten jedoch sind die gut sichtbar.
Kurz gesagt soll es ähnlich ausschauen wie oben aber mit viel weniger Punkten :)

Ich bin etwas verwirrt. Für mich sieht das Bild oben komprimiert aus, das Bild unten unkomprimiert, weil es viel mehr Details enthält. Oder verstehe ich was falsch?

Vielleicht (bestimmt) overkill, aber trotzdem zur Information: um z.B. kleine Änderungen (= hohe Frequenzen) herauszufiltern könntest du eine Fourier-Transformation machen, aus dem Spektrum die hohen Frequenzen herausnehmen und dann wieder zurücktransformieren. Sowas macht auch z.B. ein MP3 Encoder.

Grüße,
Andre
30.07.2010 19:38 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
telnet telnet ist männlich
myCSharp.de-Mitglied

Dabei seit: 14.05.2006
Beiträge: 327
Entwicklungsumgebung: Visual Studio 2013


telnet ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ich hatte mal ein ähnliches Problem, siehe  Algorithmus zur Datenaufbereitung für Diagrammdarstellung

In der Zwischenzeit habe ich eine zugekaufte Charting-Komponente verwendet, die bis zu 1 Million Datenpunkte relativ problemlos anzeigen kann.

Inzwischen habe ich aber mit Hilfe eines Mathematikers etwas gefunden, das sich "Swinging Door Algorithmus" (einfach Googlen) nennt, der perfekt für genau diesen Zweck funktioniert (Ist eigentlich eine Methode zur Datenkompression)

--> Reduktion von ca. 50000 Datenpunkten auf 3000 ohne ein einziges Pixel Unterschied auf der Grafik. Mit den Parametern muss man je nach Art der Daten dann etwas spielen... Wahrscheinlich kann man noch etwas weiter runtergehen und dennoch einen sehr guten Verlauf erzielen...

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von telnet am 30.07.2010 19:51.

30.07.2010 19:48 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien

Themenstarter Thema begonnen von michlG

michlG ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Leute,

erstmal vielen Dank für die zahlreichen Antworten.

@gfoidl: Danke für den Code, das werd ich ausprobieren

@corpsegrinder: Danke für den Tipp, das hab ich jetzt mal versucht und ein viel viel besseres Ergebnis erzielt. Mit ein paar Verfeinerungen wäre das schon mehr als ausreichend

@MarsStein: Theoretisch wäre das kein Problem wenn man die Kurven selbst zeichnet, aber ich verwende das Charting-Control von Syncfusion. Und dabei hau ich einfach die Daten rein und das Control zeigt sie an. Deshalb hab ich da keinen Eingriff

@VizOne: Das obere ist schon das unkomprimierte Bild, das ist sicher.
Ich habe auch nicht ganz verstanden wieso er mir bei der komprimierten Variante diese Spitzen darstellt. Durch das Berechnen des Durchschnittwertes müssten eigentlich die Spitzen wegfallen... Da war wohl irgendwo ein Bug in meinem Algorithmus versteckt..

Zitat:
Vielleicht (bestimmt) overkill, aber trotzdem zur Information: um z.B. kleine Änderungen (= hohe Frequenzen) herauszufiltern könntest du eine Fourier-Transformation machen, aus dem Spektrum die hohen Frequenzen herausnehmen und dann wieder zurücktransformieren. Sowas macht auch z.B. ein MP3 Encoder.

Ja ist wirklich etwas overkill :)

@telnet: Thx für den Tipp, das werde ich mir mal angucken.
PS: Was hast du für eine Charting-Komponente gekauft? Weil das Syncfusion Ding braucht eine Minute um 100.000 Punkte darzustellen und benötigt dabei 1GB RAM!

Aber mittlerweile bin ich schon dabei das ganze Syncfusion Zeug aus meinen Programmen zu entfernen. Grund dafür sind unglaublich viele Bugs welche zwar nach genauer beschreibung schnell gefixt werden, aber beim nächsten größeren Update kommen die alten Bugs wieder ans Tageslicht und dazu noch X neue!

Vielen Dank euch allen

Gruss
Michael

//EDIT:
Ich habe es jetzt mit corpsegrinders vorschlag gemacht. Relativ einfach und das Ergebnis ist gut

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von michlG am 30.07.2010 20:38.

30.07.2010 20:09 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
telnet telnet ist männlich
myCSharp.de-Mitglied

Dabei seit: 14.05.2006
Beiträge: 327
Entwicklungsumgebung: Visual Studio 2013


telnet ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn du die Daten transformierst, filterst und danach wieder zurücktransformierst bekommst du aber doch auch wieder die gleiche Anzahl Datenpunkte, nur das "Gezappel" des Graphen wird geringer, oder?

Ich persönlich habe bisher immer nur die Komponenten von DevExpress eingesetzt.. bin vor allem mit dem Support sehr zufrieden (wirkliche Bugs werden i.d.R. in weniger als einer Woche gefixt) und die Performance ist größtenteils auch wirklich gut.
30.07.2010 21:00 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien

Themenstarter Thema begonnen von michlG

michlG ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Zitat:
Wenn du die Daten transformierst, filterst und danach wieder zurücktransformierst bekommst du aber doch auch wieder die gleiche Anzahl Datenpunkte, nur das "Gezappel" des Graphen wird geringer, oder?

Nö, dadurch hab ich viel weniger Punkte.

Kurz gesagt hab ich folgenden Code:
Hier gibt es noch ein paar kleinere Anpassungen mit der ich es ein bisschen einstellen kann wie die Daten zusammengefügt werden.

C#-Code:
int maxCombine = 0;
double initialValue = values[0];

for (int i = 1; i < values.Count; i++)
{
    var abweichung = (values[i] * 0.01) * Diagramm.KomprimierungMaxAbweichung;
    if (maxCombine < Diagramm.KomprimierungMaxNebeneinander && initialValue < values[i] + abweichung && initialValue > values[i] - abweichung)
    {
        if (maxCombine == 0)
        {
            initialValue = values[i];
        }

        values[i - 1] = (values[i - 1] + values[i])  * 0.5;
        values.RemoveAt(i);
        dateTimes.RemoveAt(i);
        i--;
        maxCombine++;
    }
    else
    {
        maxCombine = 0;
        initialValue = values[i];
    }
}

Er geht also die Punkte der Reihe nach durch und vergleicht den aktuellen wert mit dem vorherigen. Wenn diese beiden nicht mehr als 10% voneinander abweichen dann werden diese zusammengefügt.
Im nächsten Schritt beginnt das selbe spiel mit dem nächsten punkt.
Beendet wird das Ganze wenn man am Ende der Liste ist.

Gruss
Michael

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von michlG am 30.07.2010 22:59.

30.07.2010 21:10 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
telnet telnet ist männlich
myCSharp.de-Mitglied

Dabei seit: 14.05.2006
Beiträge: 327
Entwicklungsumgebung: Visual Studio 2013


telnet ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich hätte vielleicht dazuschreiben sollen, dass ich die Fourier-Transformation gemeint habe....
30.07.2010 21:29 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
gfoidl gfoidl ist männlich
myCSharp.de-Team

avatar-2894.jpg


Dabei seit: 07.06.2009
Beiträge: 6.659
Entwicklungsumgebung: VS 2019
Herkunft: Waidring


gfoidl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo Michael,

wenn bei deinem Ansatz noch Spikes (= Ausreißer = lokalisierte Störung) in Folge von Messfehlern, etc. ausgefiltert werden sollen dann wärs genau mein obiger Ansatz ;-)

Da du viele Messwerte hast erstetz in deinem Code noch /100 durch *0.01 und /2 durch *0.5 -> ist schneller, denn der Compiler kapiert das nicht von selbst (und diese Optimierung ist auch nicht "premature" ;-)



Hallo telnet,

Zitat von telnet:
Wenn du die Daten transformierst, filterst und danach wieder zurücktransformierst bekommst du aber doch auch wieder die gleiche Anzahl Datenpunkte, nur das "Gezappel" des Graphen wird geringer, oder?

So ist es. Daher wird beim erwähnten MP3 auch eine Art Wavelt-Kompression verwendet. D.h. vereinfacht ausgedrückt wird das Gesamtsignal in Teile zerlegt und von jedem Teil werden nicht mehr die Abtastwerte der Amplitude gespeichert sondern nur die Parameter der Wavelet-Funktion und der zeitliche Ort. Somit lässt sich durch Umkehrung das Signal fast wieder Original herstellen. Vor der Komprimierung werden jedoch mittels FFT-Filter die Teile ausgefilter die der Mensch eh nicht wahrnehmen kann (-> "Rohdatenreduktion" vor der Komprimierung).



mfG Gü

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von gfoidl am 02.08.2010 11:50.

30.07.2010 21:37 Beiträge des Benutzers | zu Buddylist hinzufügen
michlG michlG ist männlich
myCSharp.de-Poweruser/ Experte

avatar-2909.png


Dabei seit: 26.07.2007
Beiträge: 3.430
Entwicklungsumgebung: VS 2010 PRO
Herkunft: Naturns - Südtirol - Italien

Themenstarter Thema begonnen von michlG

michlG ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Zitat von gfoidl:
wenn bei deinem Ansatz noch Spikes (= Ausreißer = lokalisierte Störung) in Folge von Messfehlern, etc. ausgefiltert werden sollen dann wärs genau mein obiger Ansatz ;-)

Nö, ich weiss auch nicht ob das wirklich Messfehler sind, oder ob diese Spitzen so gehören.
Mir wurden nur die Daten zum Testen gegeben, und falls es Messfehler sind dann sollen die Benutzer meines Controls selbst filtern :)
Aber vielen Dank für den Tipp.

Zitat:
Da du viele Messwerte hast erstetz in deinem Code noch /100 durch *0.01 und /2 durch *0.5 -> ist schneller, denn der Compiler kapiert das nicht von selbst (und diese Optimierung ist auch nicht "premature" ;-)

Hab gar nicht gewusst dass unser Compiler so doof ist :)
Jedenfalls hab ich es jetzt angepasst. Thx

Gruss
Michael
30.07.2010 22:59 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 10 Jahre.
Der letzte Beitrag ist älter als 10 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 20.09.2020 09:50