2016-08-05 43 views
0

Ich weiß, diese Frage fällt in die Kategorie der Peak-Erkennung und there are answers available, aber ich denke, mein Problem ist ziemlich einfach und bezieht sich auf einen Beweis des Prinzips.Python: korrekte Position von Peaks in einem zweidimensionalen Array?

sagen, dass ich mehrere, nxn 2D numpy Arrays von Float-Werte wie diese erzeugen, die zu einem regelmäßigen Gitter von nxn Punkte (diskrete Domäne) beziehen:

myarray= 
array([[ 0.82760819, 0.82113999, 0.811576 , 0.80308705, 0.81231903, 
     0.82296263, 0.78448964, 0.79308308, 0.82160627, 0.83475755, 
     0.8580934 , 0.8857617 , 0.89901092, 0.92479025, 0.91840606, 
     0.91029942, 0.88523943, 0.85798491, 0.84190422, 0.83350783, 
     0.83520675], 
     [ 0.84971526, 0.84759644, 0.81429419, 0.79936736, 0.81750327, 
     0.81874686, 0.80666801, 0.82297348, 0.84980788, 0.85698662, 
     0.87819988, 0.89572185, 0.89009723, 0.90347858, 0.89703473, 
     0.90092666, 0.88362073, 0.86711197, 0.84791422, 0.83632138, 
     0.83685225], ...] #you can generate any nxn array of random values 

die sie Nun lassen Sie normalisieren:

peak_value=myarray.max() 
norm_array=myarray/peak_value 

Und damit fortfahren, die (x,y) Koordinaten der Spitze zu finden:

from collections import Counter 
longit=[] #x values of the peak 
latit=[] #y values of the peak 
for x in range(myarray.shape[0]): 
    for y in range(myarray.shape[1]): 
     if norm_array[x][y]==1: 
     longit.append(x) 
     latit.append(y) 

x=numpy.array(longit) 
y=numpy.array(latit) 

c=zip(x,y) 
temp=Counter(elem for elem in c) #Counts the number of peaks in each (x,y) point in the 11x11 grid 
d=dict(Counter(temp)) #Has the shape d={(x,y): number of peaks} 

Nun ist dies nur eine einzige Realisierung der 2D-Numpy-Array. Bei mehreren Arrays lautet die Frage:

Ist das der richtige Weg, um die (x, y) der Peaks zu finden? Gibt es einen effizienteren Weg? Berücksichtigen Sie, dass mehrere Peaks vorhanden sein können.

Antwort

2

In C/C++ ist es gefährlich, == mit Fließkommazahlen zu tun.

Wenn es keine mehr exakt gleichen Hechte sind, können Sie numpy.argmax verwenden:

a = random.rand(13, 11) 
idx_unrolled = argmax(a) 
the_peak = a[idx_unrolled/11, idx_unrolled%11] 

Wenn Sie alle Hechte benötigen, können Sie die Liste i bekommen können, j Indizes numpy.where mit:

i, j = where(a > 0.99*the_peak) 

Verwenden Sie die erforderliche Anzahl von 9, um den Rand einzustellen. Für Gleitkommazahlen einfacher Genauigkeit ist es nicht nahe 1.

Der beste Weg, kann so etwas wie [https://stackoverflow.com/a/19141711/774971] sein:

i, j = where(a > (1.0 - 5*np.finfo(a.dtype).eps)*the_peak) 
+0

Nun, ich weiß es nicht. Es könnte mehrere Spitzen geben. Was schlägst du in diesem Fall vor? – FaCoffee

+0

Auch meine Frage ist nicht über den Wert von meinem Max, da ich das Array normalisieren. Es handelt sich um seine Koordinaten im Raster. Also deine letzte Zeile, ich brauche sie nicht, da mein Max immer 1,0 ist. – FaCoffee

+2

Ich habe mehrere Peaks in der neuen Version gemacht. Mein Punkt über 'max' ist, dass du' 0.99999999999' statt '1.00000000000' bekommst und du deinen Peak komplett verpasst. Das passiert in der Fließkomma-Arithmetik, besonders wenn Sie viel rechnen oder modellieren [http://floating-point-gui.de/errors/comparison]. –