Das Problem besteht darin, die Ausbreitung eines Signals (z. B. Licht oder Ton usw.) durch eine Reihe von Hindernissen zu modellieren, wie in der folgenden Abbildung dargestellt. Das Signal kann nicht durch die Bodenfläche (Gelände) geleitet werden, es kann jedoch Hindernisse überwinden. Ich möchte die Anzahl der durchquerten Hindernisse zählen.
Gelände und Hindernisse befinden sich in 2D-Numpy-Arrays (x, y, z). Das ist was ich mache:
output = numpy.zeros(terrain.shape)
obstacles = terrain + obstacle_heights
for i in xrange (obstacles.shape[0]):
for j in xrange (obstacles.shape[1]):
mask = obstacles[i,j] > terrain[i,j:]
output[i,j:][mask] +=1
Das Ergebnis wäre so etwas wie [0, 0, 0, 1, 1, 1, 2, 3, 4, 4, 4 ...]
pro Zeile.
Diese Methode funktioniert einwandfrei (vorausgesetzt, die Täler im Gelände werden mit verwendet numpy.maximum.accumulate
). Wäre es nun möglich, die Sache mit einer vektorisierten Lösung zu beschleunigen?
Antworten:
Wie in den obigen Kommentaren angegeben, können Sie die Operation wahrscheinlich vektorisieren, um die for-Schleifen zu entfernen und effizienter zu gestalten.
Wenn Sie das Problem jedoch auf eine etwas andere Art und Weise betrachten - die des Schwellenwerts -, können Sie die Tools von scipy ndimage nutzen, um die Hindernisse zu zählen:
Schwellen Sie zunächst Ihre Geländedaten anhand Ihrer Signalhöhe, um unabhängig vom Ursprung ein boolesches Array zu erhalten, in dem sich das Signal befinden könnte.
Dann können Sie die
ndimage.label
Methode verwenden, um diskrete Regionen zu gruppieren:Sobald dies erledigt ist, erhalten Sie die Regions-IDs, die mit den Ursprungszellen Ihres Signals übereinstimmen. In Ihrem Fall wäre es die erste Spalte.
Jetzt liegt der Schwellenwert dort, wo das Signal das Gelände + Hindernisse abfängt, und dieses Mal werden Bereiche außerhalb oder außerhalb des interessierenden Bereichs mithilfe von herausgefiltert
numpy.isin
.In einer letzten Runde von können
ndimage.label
Sie die abgefangenen Hindernisse zählen, da wir bereits vom Gelände blockierte Bereiche herausgefiltert haben:Hier gibt es etwas mehr Code, aber es gibt zwei große Vorteile:
quelle