2017-12-28 16 views
2

ich den folgenden Code-Schnipsel haben (Hough Kreis-Transformation):Vektorisierung Python-Code numpy

for r in range(1, 11): 
    for t in range(0, 360): 
     trad = np.deg2rad(t) 

     b = x - r * np.cos(trad) 
     a = y - r * np.sin(trad) 

     b = np.floor(b).astype('int') 
     a = np.floor(a).astype('int') 

     A[a, b, r-1] += 1 

Wo A eine 3D-Anordnung von Form ist (height, width, 10) und height und width repräsentieren die Größe eines bestimmten Bildes . Mein Ziel ist es, das Snippet ausschließlich in numpy Code zu konvertieren.

Mein Versuch ist dies:

arr_r = np.arange(1, 11) 
arr_t = np.deg2rad(np.arange(0, 360)) 

arr_cos_t = np.cos(arr_t) 
arr_sin_t = np.sin(arr_t) 

arr_rcos = arr_r[..., np.newaxis] * arr_cos_t[np.newaxis, ...] 
arr_rsin = arr_r[..., np.newaxis] * arr_sin_t[np.newaxis, ...] 

arr_a = (y - arr_rsin).flatten().astype('int') 
arr_b = (x - arr_rcos).flatten().astype('int') 

Wo x und y sind zwei skalare Werte.

Ich habe Probleme bei der Konvertierung der Inkrementteil: A[a,b,r] += 1. Ich dachte daran: A[a,b,r] zählt die Anzahl der Vorkommen des Paares (a,b,r), also ein Hinweis war, ein kartesisches Produkt zu verwenden (aber die Arrays sind zu groß).

Irgendwelche Tipps oder Tricks, die ich verwenden kann?

Vielen Dank!

Edit: nach dem Füllen A, brauche ich (a,b,r) als argmax(A). Das Tupel (a,b,r) identifiziert einen Kreis und sein Wert in A repräsentiert den Konfidenzwert. Also ich möchte das Tupel mit dem höchsten Wert in A. Dies ist Teil des Abstimmungsalgorithmus von Hough circle transform: find circle parameter with unknown radius.

+0

Ja, ich habe es behoben. – Alex

+0

Gibt es einen Grund, warum Sie eine Dimension für "r" in "A" haben? Es scheint überflüssig. –

+0

@PaulPanzer - nach dem Füllen 'A' brauche ich' (a, b, r) 'als' argmax (A) '. Das Tupel '(a, b, r)' identifiziert einen Kreis und sein Wert in 'A' repräsentiert den _Konfidenzwert_. Also möchte ich das Tupel mit dem höchsten Wert in 'A'. – Alex

Antwort

3

Methode # 1

Hier ist eine Möglichkeit broadcasting Nutzung der Zählungen zu erhalten und aktualisieren A (diese übernimmt die ab und in den Zwischenschritten berechneten Werte sind positiv sind) -

d0,d1,d2 = A.shape  
arr_r = np.arange(1, 11) 
arr_t = np.deg2rad(np.arange(0, 360)) 

arr_b = np.floor(x - arr_r[:,None] * np.cos(arr_t)).astype('int') 
arr_a = np.floor(y - arr_r[:,None] * np.sin(arr_t)).astype('int') 

idx = (arr_a*d1*d2) + (arr_b * d2) + (arr_r-1)[:,None] 

A.flat[:idx.max()+1] += np.bincount(idx.ravel()) 
# OR A.flat += np.bincount(idx.ravel(), minlength=A.size) 

Methode # 2

Alternativ könnten wir bincount vermeiden den letzten Schritt in approach #1 zu ersetzen, wie so -

idx.ravel().sort() 
idx.shape = (-1) 
grp_idx = np.flatnonzero(np.concatenate(([True], idx[1:]!=idx[:-1],[True]))) 
A.flat[idx[grp_idx[:-1]]] += np.diff(grp_idx) 

Verbesserung mit numexpr

Wir auch numexpr module für schnelleren Sinus, Cosinus-Berechnungen nutzen könnten, wie so -

+0

Ich muss erwähnen, dass diese beiden "for" -Schleifen unter zwei weiteren for-Schleifen verschachtelt sind ('for x' und' for y'). Ich muss das für jedes '(x, y)' berechnen. – Alex

+0

@Alex Aber die Frage lautet - 'Wo x und y sind zwei skalare Werte? – Divakar

+0

Sie sind Skalare (Indizes). Dieser Code wird für jedes '(x, y)' ausgeführt. – Alex

2

np.add (np.array ([arr_a, arr_b, 10]), 1)

+0

Was genau machst du hier?Ich sehe überall Tippfehler und kann immer noch nicht erkennen, wie einfach die Indizierung mit diesen Index-Arrays funktionieren würde. – Divakar

+0

Sorry für den Tippfehler. Korrigiert es. Ich habe verstanden, dass Alex die drei Werte in seinem Array mit numpy erhöhen möchte, was die obige Zeile tut. Er schrieb auch, dass r immer 10 ist, also habe ich den Wert fest codiert. – Thomas

+0

Und wie aktualisieren Sie 'A'? – Divakar