Forum: PC-Programmierung Maxima in einem Histogramm suchen


von Philipp (Gast)


Lesenswert?

Hallo,

ich frage mich, wie ich Peaks in einem Histogramm (oder von mir aus in 
einer Folge) suchen kann.

Beispiel:
0 0 2 3 5 6 4 3 2 1 1 1 0 0 0 1 1 2 1 2 2 3 4 5 6 7 7 8 9 9 6 5 3 2 1 2 
0

--> hier möchte ich gerne die Werte "6" und "9" haben, da sie die beiden 
"Stärksten" lokalen Maxima darstellen.

Ableiten (also Differenz bilden) und nach den Übergängen "+" nach "-" 
suchen? Hat jemand ein Stichwort für ein Verfahren, nach dem ich suchen 
kann?

von Valentin B. (nitnelav) Benutzerseite


Lesenswert?

Hmm.
Mathematisch oder Informatisch?

Mathmatisch ist klar, erste und zweite Ableitung und dann lokale 
Extremstellen finden.

Informatisch würde ich das so lösen:
1
Gucken ob Wert größer 0
2
Wenn ja{ 
3
   Vergleich mit tempörärem Speicher
4
   Wenn größer{
5
      temporären Speicher ersetzen
6
              }
7
   }
8
Wenn nein{
9
   Temporärer Speicher größer 0?
10
   Wenn ja{
11
      temporären Speicher ausgeben
12
          }
13
   temporären Speicher löschen (gleich 0 setzen)
14
   }

Ich hoffe du verstehst wie ich das meine.
Mit freundlichen Grüßen,
Valentin Buck

von Klaus W. (mfgkw)


Lesenswert?

Braucht man dafür ein Verfahren?
Man geht das Feld entlang, berechnet die Differenz und merkt
sich die jeweils letzte.
Ist die letzte >0, übergeht man alle ==0 und schaut sich dann
die erste !=0 an. Falls <0: Maximum gefunden, sonst nur Sattelpunkt im
Aufstieg, also aktuelle Diff. zu letzter machen und weiter wie oben.

von Valentin B. (nitnelav) Benutzerseite


Lesenswert?

@ Klaus Wachtler:
Das habe ich versucht in Worte zu fassen!
Ich hätte nie so einfach gedacht... ;-)

Mit freundlichen Grüßen,
Valentin Buck

von Karl H. (kbuchegg)


Lesenswert?

Aber Vorsicht:
Der erste und der letzte Punkt brauchen eine Sonderbehandlung!

von Philipp (Gast)


Lesenswert?

hüstel ich glaube es ist ziemlich einfach. Ich will die beiden 
stärksten lokalen Maxima suchen:
1
int max1 = 0;
2
int max2 = 0;
3
4
int pos1 = 0;
5
int pos2 = 0;
6
7
for (int i = 0; i < BINS; i++){
8
   int delta = f[i+1] - f[i];
9
10
   if (delta < 0){               // lokales Maximum
11
      if (f[i] > max1){          // neues globales Maximum
12
         max2 = max1;
13
         pos2 = pos1;
14
         max1 = f[i];
15
         pos1 = i;
16
      }
17
      else if (f[i] > max2){    // neues zweitgr. lok. Max.
18
         max2 = f[i];
19
         pos2 = i;
20
      }
21
   } 
22
23
}

Ich glaube, so kann es wohl funktionieren.

von Philipp (Gast)


Lesenswert?

... mit der Einschränkung natülich, dass ich BINS-1 nehmen muss um beim 
letzten Schritt nicht ins Leere zu laufen, aber das hat Karl Heinz ja 
bereits angesprochen.

von Karl H. (kbuchegg)


Lesenswert?

Philipp schrieb:

> Ich glaube, so kann es wohl funktionieren.

Das denke ich nicht.
Das ist ein bischen zu einfach überlegt.

Aber probiers durch.

von Philipp (Gast)


Lesenswert?

Hast Recht, ich muss wohl erst tiefpassfiltern oder so etwas, hier 
schlägt es z.B. fehl:

999 1001 999 1001 1050 1001 999 0 0 0 0 0 0 1000 0 0 0 0

Offensichtlich "will" ich hier gerne die Positionen mit 1050 und 1000 
haben, bekomme aber natürlich 1001 und 1050, die ja beim Blick auf das 
Histogramm auf dem gleichen Berg liegen.

Also muss ich sowas machen: Berg raufklettern, höchsten Punkt finden und 
dann erst wieder einen neuen höchsten Punkt suchen, wenn ich in einem 
Tal war.

von Karl H. (kbuchegg)


Lesenswert?

Philipp schrieb:

> Also muss ich sowas machen: Berg raufklettern, höchsten Punkt finden und
> dann erst wieder einen neuen höchsten Punkt suchen, wenn ich in einem
> Tal war.

Jupp

Das wäre auch mein Ansatz
abwechselnd Maximum und Minimum suchen

wobei das Problem eigentlich nur am Anfang besteht: Womit fängt man an? 
Sucht man ein Maximum oder ein Minimum (lässt sich aber lösen, indem man 
sich den/die nächsten Punkte ansieht, wie dort die 'Steigung' verläuft. 
Ist sie positiv dann gilt der erste Punkt schon als Minimum und man 
sucht ein Maximum. Ist sie negativ, dann gilt der erste Punkt schon als 
Maximum und man sucht ein Minimum. Steigung 0 gilt nicht, dann muss man 
eben den übernächsten Punkt betrachten, fff)

Und dann gehts eigentlich immer so dahin
1
  schleife über alle Elemente {
2
3
    if modus == maximum suchen
4
       if steigung < 0 then
5
         maximum gefunden
6
         entscheiden ob man es aufheben will (nur die 2 Größten)
7
         modus = minimum suchen
8
9
    else if modus == minimum suchen
10
       if steigung > 0 then
11
         modus = maximum suchen
12
  }

nur so als Codeskizze

Der letzte Punkt bedarf noch einer Sonderbahandlung. Er könnte ja ein 
Maximum sein, obwohl es keinen Steigungswechsel mehr gibt. Einfach in 
die Funktion, die entscheidet, ob man ein Maximum aufheben will als 
"Maximum" einfliessen lassen. Wenn er tatsächlich ein Maximum ist, dann 
hebt ihn sich die Funktion dann schon auf.

von Philipp (Gast)


Lesenswert?

Hm, also über die "Grundfunktion" bin ich mir ja durchaus im Klaren, 
allerdings gibt es ja den kleinen Haken dass z.B. bei

1 2 3 5 3 2 3 2 1 0 0 0 1 2 1 0 0 0

die "3" (Position 7) nicht als Maximum durchgehen soll, es ist ja 
offensichtlich nur "Messrauschen". Daher mein Gedanke, das 
Tiefpasszufiltern bzw. exponentiell zu Glätten oder sowas. Oder ich 
benutze sowas wie den "Floodfill"-Algorithmus --> ich "flute" meine 
Folgen bis zu einem gewissen Wert, dann bleiben nur noch einzelne Inseln 
übrig und ich suche dann nur noch das globale Maximum pro Insel. Hier 
also: Füllen bis "1" (ok, hier jetzt witzlos da die Zahlen ja recht nahe 
beisammen liegen):

1 2 3 5 3 2 3 2 1 1 1 1 1 2 1 1 1 1

Es bleiben also zwei Inseln übrig und ich finde die 5 und die 2. 
Natürlich würde das in diesem Beispiel auch mit "0" als Fluthöhe 
funktionieren, aber da meine Täler ja auch bei 5 oder 10 liegen können, 
brauche ich also einen Wert, der so groß wie möglich ist aber kleiner 
als meine erwarteten Spitzen.

50 70 50 400 200 300 100 10 20 80 100 50 50

Füllen bis z.B. 60:

60 70 60 100 200 300 100 60 60 80 100 60 60

... und ich finde, wenn ich die beiden größten suche, 400 und 100, aber 
nicht die 300.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.