Zählen aufeinanderfolgender Pixelwerte für eine Reihe von Rastern mit ArcGIS Spatial Analyst?

23

Ich verwende ArcGIS 10 mit Spatial Analyst.

Ich habe eine Reihe von Rastern (insgesamt 8), die nur jeweils eine 1 oder eine 0 für jede Zelle enthalten. Jedes Raster repräsentiert einen unterschiedlichen Datenwert für ein Jahr. Aus Gründen von Jahr 1 bis Jahr 8.

Ich kann alle Raster zusammenaddieren, um ein endgültiges Raster mit Werten zwischen 0 und 8 zu erhalten. Eine 8 gibt an, dass die Zelle für die Gruppe der Raster (alle Jahre) konstant 1 war.

Ich möchte für jede Zelle die längste fortlaufende Zahl von Einsen herausfinden.

So kann beispielsweise das Gesamtgitter für eine einzelne Zelle einen Wert von beispielsweise 5 aufzeichnen, aber über den 8 Gittern hat diese Zelle die größte fortlaufende Zahl von 1 gleich 3. Oder eine andere Art, dies auszudrücken, ist für 3 Jahre, dass die Zelle eine 1 war dann begann es zwischen Nullen und Einsen zu pendeln.

Meine Fähigkeiten in der Rasterverarbeitung sind nicht so gut wie in der Vektorbearbeitung, und ich habe mir die ESRI-Hilfedatei genau angesehen, kann aber nicht herausfinden, wie dies mit Standard-Geoverarbeitungswerkzeugen erreicht werden kann.

Irgendwelche Ideen?

Hornbydd
quelle
1
Das ist eigentlich eine ziemlich coole Analyse. Wie üblich gibt es mehr als eine Möglichkeit, das zu tun, was Sie versuchen. Ich denke, Sie müssen etwas programmieren, um alle Kombinationen durchzuarbeiten.
MLowry
1
Ein allgemeiner Kommentar (inspiriert von dieser Bemerkung von @MLowry): Bitte stimmen Sie Fragen zu, wenn sie interessant aussehen oder klar formuliert sind. Gute Fragen bestimmen alles auf unserer Website. Bitte lasst uns tun, was wir können, um diejenigen zu belohnen, die sie fragen!
Whuber

Antworten:

14

Da es sich um eine lokale Operation handelt, wollen wir herausfinden, wie dies für eine einzelne Zelle durchgeführt wird: Map Algebra kümmert sich um den Rest.

Beachten Sie zunächst, dass die Reihenfolge der Raster offensichtlich von Bedeutung ist. Daher reicht eine Einzelbild-Zellstatistik wie eine Zellensumme nicht aus.

Wenn wir in einer bestimmten Zelle auf eine Sequenz wie 01110101 stoßen, verarbeiten wir diese vom Anfang bis zum Ende und

  1. Beginnen Sie mit einer Zählung bei Null.

  2. Erhöhen Sie die Anzahl jedes Mal, wenn wir auf eine 1 stoßen.

  3. Setzen Sie die Zählung jedes Mal zurück, wenn eine 0 auftritt, nachdem Sie die letzte Zählung gespeichert haben .

  4. Nehmen Sie am Ende die maximal gespeicherte Anzahl (einschließlich der endgültigen Anzahl).

Schritt 1 wird mit einem konstanten Nullgitter implementiert. Die Schritte 2 und 3 hängen davon ab, was uns begegnet: Es ist daher eine bedingte Operation. Schritt 4 ist eindeutig ein lokales Maximum. Wir würden das also etwas formeller kodieren als:

count = 0
result = 0
For each value:
    If (value==1):
        count=count+1
    else
        result = max(result, count)
        count=0
result = max(result, count)

Das geht am besten mit einem Python-Skript, wenn Sie viele Gitter haben, aber mit acht ist es nicht mühsam, die Schleife zu entrollen und die Schritte von Hand aufzuschreiben. Dies zeigt ein kleines Problem: Dies result=max(longest,count)ist eine Art "Nebeneffekt", der mit Rasteroperationen nur schwer zu programmieren ist. (Dies ist jedoch möglich, wie in der folgenden zweiten Lösung gezeigt.) Dies ist auch ineffizient, da bei jedem Schritt eine zusätzliche Berechnung hinzugefügt wird. Wir ändern daher den Ansatz ein wenig, um die maxOperation bis zum Ende hinauszuschieben. Dies erfordert das Speichern einer separaten Zählung in jeder Phase.

Dabei habe ich auch eine Abkürzung für den ersten Schritt gefunden. Dies führt zu der folgenden Lösung, die zwar etwas langwierig und RAM-intensiv ist, jedoch einfach ist und schnell auszuführende Schritte umfasst:

result1 = "grid1"
result2 = con("grid2"==1, "result1"+1, 0)
result3 = con("grid3"==1, "result2"+1, 0)
result4 = con("grid4"==1, "result3"+1, 0)
result5 = con("grid5"==1, "result4"+1, 0)
result6 = con("grid6"==1, "result5"+1, 0)
result7 = con("grid7"==1, "result6"+1, 0)
result8 = con("grid8"==1, "result7"+1, 0)
CellStatistics(["result1", "result2", "result3", "result4", "result5", "result6", "result7" "result8"], "max")

Die tatsächliche Syntax hängt von Ihrer Version von ArcMap ab. (Ist zum Beispiel CellStatisticsneu in Version 10, glaube ich, aber eine lokale maximale Operation war immer verfügbar.)

Im Beispiel mit der Eingabe 01110101 würde die Folge von "result *" - Gittern die Werte 0, 1, 2, 3, 0, 1, 0, 1 enthalten, sodass am Ende CellStatistics3 zurückgegeben würde, die Länge der längsten Zeichenfolge von 1's.

Wenn der Arbeitsspeicher knapp ist, kann die Lösung so geändert werden, dass die Zwischenergebnisse wiederverwendet werden. Dies kostet ungefähr das Doppelte der Ausführungszeit:

result = "grid1"
temp = con("grid2"==1, "result"+1, 0)
result = CellStatistics[["temp", "result"], "max"]
temp = con("grid3"==1, "temp"+1, 0)
result = CellStatistics[["temp", "result"], "max"]
...
temp = con("grid8"==1, "temp"+1, 0)
CellStatistics[["temp", "result"], "max"]

In dem Beispiel mit Eingabe 01110101 wären die Werte ("temp", "result") nach der ersten Zeile (NoData, 0) und nach jedem Paar von ("Con", "CellStatistics") - Operationen wären die Werte (1) , 1), (2, 2), (3, 3), (0, 3), (1, 3), (0, 3), (1, 3). Der Endwert ist wieder 3.

Das reguläre Muster von Map Algebra-Ausdrücken in beiden Lösungen gibt an, wie der Algorithmus als Schleife in einem Skript codiert wird, wobei die Indizes bei jeder Iteration entsprechend geändert werden.

whuber
quelle
Es könnte ein Tippfehler im Typcode-Block sein: count = count = 1 sollte wahrscheinlich count = count + 1 sein
MLowry
1
@ML Danke (gute Augen!): Es ist jetzt behoben. Es ist schwierig, den Pseudocode absolut korrekt zu machen. Human Review ist eine echte Hilfe bei der Fehlersuche. Obwohl ich die Lösungen in ArcGIS nicht getestet habe, habe ich die erste Lösung in R implementiert, sodass ich mir sicher bin, dass der Ansatz korrekt ist.
whuber
1
"whuber" noch einmal du bist der Mann, der weiß! Gott helfe uns allen, wenn du jemals von einem Bus überfahren wirst! Ihr ursprünglicher Python-Ansatz war die Richtung, an die ich gedacht habe, aber ich weiß, dass man mit Rastern oft alles machen kann, was Sie bewiesen haben. Wenn Sie sich in Großbritannien befinden, wäre es eine Ehre, Ihnen ein Pint unseres besten Raumtemperatur-Flachbiers zu kaufen! :)
Hornbydd
Danke, Duncan. Aber sehen Sie sich die hervorragende Lösung von Andy Harfoot an!
whuber
14

Chatten Sie einfach darüber und fragen Sie sich, ob Sie das Problem angehen können, indem Sie die Eingaberaster als Binärdatenstrom behandeln. Auf diese Weise können Sie sie kombinieren, um eine eindeutige zusammenfassende Ganzzahl für die Sequenz zu erhalten - dh 01110101 = 117. Dieser Wert kann dann neu klassifiziert werden, um die maximale Anzahl aufeinanderfolgender Einsen zu erhalten.

Das folgende Beispiel zeigt eine Möglichkeit zum Kombinieren von acht Gittern:

2*(2*(2*(2*(2*(2*(2*"g8" + "g7") + "g6") + "g5") + "g4") + "g3") + "g2") + "g1"

Für diesen Schritt könnten auch bitweise Operationen in Betrieb genommen werden. Alternativ können Sie kombinieren, gefolgt von einer Feldberechnung. (Die Feldberechnung hat einen ähnlichen Ausdruck wie die vorhergehende.)

Die Reklassifizierungstabelle muss die maximalen Lauflängen für alle Werte zwischen 00000000B = 0 und 11111111B = 255 angeben. In der angegebenen Reihenfolge sind dies:

0, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 6, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 6, 7, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 1, 1, 1, 2, 1, 1, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 1, 1, 1, 2, 1, 1, 2, 3, 1, 1, 1, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 5, 6, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 3, 4, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 3, 4, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8

Dieser Ansatz ist in ArcGIS auf etwa 20 Grids beschränkt: Wenn Sie mehr als dieses verwenden, kann eine unhandliche Attributtabelle erstellt werden. ( Combineist speziell auf 20 Raster begrenzt.)

Andy Harfoot
quelle
Ein riesiges +1: Dies ist eine sehr gute Idee. (Die einzige Einschränkung besteht darin, dass bei mehr als 31 Grids nicht mehr genügend Bits zur Verfügung stehen.) Ich habe mir die Freiheit genommen, Ihre Idee ein wenig zu konkretisieren, damit andere erkennen, wie einfach die Implementierung ist.
whuber
3

Haben Sie daran gedacht, die Werte von 0 und 1 in Werte mit der Potenz 2 (1,2,4,8,16,32) zu ändern? Wenn Sie die 8 Gitter kombinieren, erhalten Sie eindeutige Werte für jede Zelle, die aufeinanderfolgende Informationen liefern (dh: ein Wert von 3 bedeutet Jahr 1 und 2, wobei ein Wert von 54 die Jahre 6 bis 8 bedeuten würde).

Nur ein Gedanke

Ryan Garnett
quelle
Genau das hat @Andy Harfoot ein paar Stunden zuvor vorgeschlagen, Ryan. :-)
whuber
Danke und Entschuldigung. Ich lese das auf meinem Handy im Urlaub.
Ryan Garnett