8

Ok, also habe ich ein Histogramm (dargestellt durch ein Array von Ints), und ich suche nach dem besten Weg, lokale Maxima und Minima zu finden. Jedes Histogramm sollte 3 Spitzen haben, von denen einer (der erste) wahrscheinlich viel höher ist als der andere.Finden der lokalen Maxima/Peaks und Minima/Täler von Histogrammen

möchte ich einige Dinge tun:

  1. Finden Sie das erste „Tal“ nach der ersten Spitze (in der Reihenfolge des ersten Peaks insgesamt in das Bild, um loszuwerden)

  2. Finden Sie die optimaler "Tal" -Wert zwischen den verbleibenden zwei Peaks, um das Bild zu trennen

    Ich weiß bereits, wie man Schritt 2 durch die Implementierung einer Variante von Otsu macht. Aber ich kämpfe mit Schritt 1

  3. Falls das Tal zwischen den beiden verbleibenden Spitzen nicht niedrig genug ist, möchte ich eine Warnung geben.

Auch ist das Bild recht sauber mit wenig Rauschen zu berücksichtigen

Was die Brute-Force-Algorithmen würden die Schritte 1 und 3 zu tun? Ich könnte einen Weg finden, Otsu zu implementieren, aber die brutale Kraft entkommt mir mathematisch. Wie sich herausstellt, gibt es mehr Dokumentation über Methoden wie Otsu und weniger über das Auffinden von Gipfeln und Tälern. Ich suche nichts mehr als was immer die Arbeit erledigt (dh es ist eine temporäre Lösung, muss nur in einem vernünftigen Zeitrahmen implementierbar sein, bis ich mehr Zeit darauf verbringen kann)

Ich mache das alles in C#

Irgendwelche Hilfe, auf denen Schritte zu nehmen sind, würde geschätzt werden! Vielen Dank!

EDIT: einige weitere Daten:

meisten Histogramme sind wahrscheinlich wie die erste sein, mit dem ersten Peak darstellt Hintergrund.

Histogram

Histogram 2

+0

Könnten Sie einige Beispieldaten geben Sie bitte? – ose

+0

Sieht das Gebiet um die Gipfel wie normal verteilt aus? Sie könnten z.B. passen Sie drei unabhängige Normalverteilungen an Ihre Daten an. Dann können Sie die Standardabweichung verwenden, um Schnittpunkte zu bestimmen, um Ihre Spitzen und Täler zu identifizieren. – Andreas

+0

Wie wäre es mit einem k-Mittel Algortihm mit k = 3, um 3 verschiedene Cluster zu erhalten? Jeder Schwerpunkt sollte einem der Spitzen entsprechen, wenn die Dinge gut laufen. – Reinhard

Antwort

4

Verwenden peakiness-Test. Es ist eine Methode, um alle möglichen Spitzen zwischen zwei lokalen Minima zu finden und die Spitzenwerte basierend auf einer Formel zu messen. Wenn die Spitze höher als ein Schwellenwert ist, wird der Peak akzeptiert.

Quelle: UCF CV CAP5415 lecture 9 slides

Unten ist mein Code:

public static List<int> PeakinessTest(int[] histogram, double peakinessThres) 
{ 
    int j=0; 
    List<int> valleys = new List<int>(); 

    //The start of the valley 
    int vA = histogram[j]; 
    int P = vA; 

    //The end of the valley 
    int vB = 0; 

    //The width of the valley, default width is 1 
    int W = 1; 

    //The sum of the pixels between vA and vB 
    int N = 0; 

    //The measure of the peaks peakiness 
    double peakiness=0.0; 

    int peak=0; 
    bool l = false; 

    try 
    { 
     while (j < 254) 
     { 

      l = false; 
      vA = histogram[j]; 
      P = vA; 
      W = 1; 
      N = vA; 

      int i = j + 1; 

      //To find the peak 
      while (P < histogram[i]) 
      { 
       P = histogram[i]; 
       W++; 
       N += histogram[i]; 
       i++; 
      } 


      //To find the border of the valley other side 
      peak = i - 1; 
      vB = histogram[i]; 
      N += histogram[i]; 
      i++; 
      W++; 

      l = true; 
      while (vB >= histogram[i]) 
      { 
       vB = histogram[i]; 
       W++; 
       N += histogram[i]; 
       i++; 
      } 

       //Calculate peakiness 
      peakiness = (1 - (double)((vA + vB)/(2.0 * P))) * (1 - ((double)N/(double)(W * P))); 

      if (peakiness > peakinessThres & !valleys.Contains(j)) 
      { 
       //peaks.Add(peak);       
       valleys.Add(j); 
       valleys.Add(i - 1); 
      } 

      j = i - 1; 
     } 
    } 
    catch (Exception) 
    { 
     if (l) 
     { 
      vB = histogram[255]; 

      peakiness = (1 - (double)((vA + vB)/(2.0 * P))) * (1 - ((double)N/(double)(W * P))); 

      if (peakiness > peakinessThres) 
       valleys.Add(255); 

       //peaks.Add(255); 
      return valleys; 
     } 
    } 

     //if(!valleys.Contains(255)) 
     // valleys.Add(255); 

    return valleys; 
}