Siehe diesen Link für weitere Details.
Das Problem:
Ich möchte ein kontinuierliches Raster (eines ohne Attributtabelle) Zelle für Zelle durchlaufen und den Wert der Zelle abrufen. Ich möchte diese Werte übernehmen und Bedingungen für sie ausführen und die unten beschriebenen Schritte der Kartenalgebra emulieren, ohne den Raster-Rechner tatsächlich zu verwenden.
Auf Anfrage von Kommentaren unten habe ich Details hinzugefügt, die Hintergrundinformationen zum Problem liefern und die Notwendigkeit der Implementierung einer Methode als solche im Abschnitt "Die erforderliche Analyse" begründen.
Die unten vorgeschlagene Analyse ist zwar für mein Problem relevant, muss aber nicht in eine Antwort umgesetzt werden. Der Umfang der Frage bezieht sich nur auf die Iteration durch ein kontinuierliches Raster zum Abrufen / Festlegen der Zellenwerte.
Die Analyse benötigt:
Wenn eine der folgenden Bedingungen erfüllt ist, geben Sie der Ausgabezelle den Wert 1. Geben Sie der Ausgabezelle nur dann den Wert 0, wenn keine der Bedingungen erfüllt ist.
Bedingung 1: Wenn der Zellenwert größer ist als die oberen und unteren Zellen, geben Sie den Wert 1 an:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Wo die Kerneldatei so aussieht:
3 3
0 1 0
0 0 0
0 1 0
Bedingung 2: Wenn der Zellenwert größer als der Wert der linken und rechten Zelle ist, geben Sie den Wert 1 an:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Wo die Kerneldatei so aussieht:
3 3
0 0 0
1 0 1
0 0 0
Bedingung 3: Wenn der Zellenwert größer als die oberen und unteren rechten Zellen ist, geben Sie den Wert 1 an:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Wo die Kerneldatei so aussieht:
3 3
1 0 0
0 0 0
0 0 1
Bedingung 4: Wenn der Zellenwert größer ist als die unteren linken und oberen rechten Zellen, geben Sie den Wert 1 an:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Wo die Kerneldatei so aussieht:
3 3
0 0 1
0 0 0
1 0 0
Bedingung 5: Wenn jede einer der benachbarten Zellen , die einen Wert gleich die mittleren Zelle hat, gibt die Ausgabe - Raster einen Wert von 1 ( unter Verwendung von fokaler Varietät mit zwei nächsten Nachbarschafts Berechnungen )
Warum nicht Kartenalgebra verwenden?
Im Folgenden wurde festgestellt, dass mein Problem mithilfe der Kartenalgebra gelöst werden kann. Wie oben dargestellt, handelt es sich jedoch um insgesamt sechs Raster-Berechnungen und eine, um alle erstellten Raster zusammenzuführen. Es scheint mir, dass es viel effizienter ist, Zelle für Zelle alle Vergleiche gleichzeitig durchzuführen, anstatt jede einzelne sieben Mal zu durchlaufen und eine ganze Menge Speicher für die Erstellung von sieben Rastern zu verwenden.
Wie soll das Problem angegriffen werden?
Der obige Link rät zur Verwendung der IPixelBlock-Schnittstelle. Aus der ESRI-Dokumentation geht jedoch nicht hervor, ob Sie tatsächlich über IPixelBlock auf einen einzelnen Zellenwert zugreifen oder ob Sie über die Größe des von Ihnen festgelegten IPixelBlocks auf mehrere Zellenwerte zugreifen. Eine gute Antwort sollte eine Methode für den Zugriff auf die Zellenwerte eines kontinuierlichen Rasters vorschlagen und eine Erklärung der Methodik hinter dem Code liefern, wenn nicht offensichtlich.
In Summe:
Was ist die beste Methode zum Durchlaufen jeder Zelle in einem CONTINUOUS-Raster (das keine Attributtabelle enthält ), um auf ihre Zellenwerte zuzugreifen?
Eine gute Antwort muss nicht die oben beschriebenen Analyseschritte implementieren, sondern muss nur eine Methode zum Zugreifen auf Zellenwerte eines Rasters bereitstellen.
Antworten:
Ich sehe, dass dies bereits durch das Original Poster (OP) gelöst wurde, aber ich werde eine einfache Lösung in Python veröffentlichen, nur für den Fall, dass jemand in der Zukunft an verschiedenen Möglichkeiten interessiert ist, dieses Problem zu lösen. Ich bin ein Teil der Open-Source-Software, daher hier eine Lösung mit GDAL in Python:
Implementieren Sie die Funktion wie folgt:
Durchlaufen Sie dann Ihre Daten mit einer verschachtelten Schleife:
Oder Sie möchten Ihr 2-D-Array mit einem Listenverständnis abflachen:
Wie auch immer, während Sie die Daten Zelle für Zelle durchlaufen, ist es möglich, einige Bedingungen in Ihre Schleife zu werfen, um Werte zu ändern / zu bearbeiten. In diesem Skript habe ich verschiedene Möglichkeiten für den Zugriff auf die Daten beschrieben: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .
quelle
Aktualisieren! Die numpy Lösung:
Daher ist es mühsam, das fertige Array mit arcpy wieder in das Raster zu bringen. arcpy.NumPyArrayToRaster ist squirrelly und neigt dazu, Ausmaße neu zu definieren, selbst wenn Sie Ihre LL-Koordinaten eingeben.
Ich speichere lieber als Text.
Ich verwende Python aus Geschwindigkeitsgründen als 64-Bit-Version. Dies bedeutet, dass ich numpy.savetxt derzeit nicht mit einem Header versorgen kann. Also muss ich die Ausgabe öffnen und den ASCII-Header hinzufügen, den Arc haben möchte, bevor ich ASCII in Raster konvertiere
Die numpy-Version führt mein Schichtraster, Multiplikationen und Additionen viel schneller aus (1000 Iterationen in 2 Minuten) als die arcpy-Version (1000 Iterationen in 15 Minuten).
ALTE VERSION Ich kann dies später löschen. Ich habe gerade ein ähnliches Skript geschrieben. Ich habe versucht, in Punkte umzuwandeln und den Suchcursor zu verwenden. Ich habe in 12 Stunden nur 5000 Iterationen erhalten. Also suchte ich einen anderen Weg.
Meine Methode besteht darin, die Zellmittelpunktkoordinaten jeder Zelle zu durchlaufen. Ich beginne in der oberen linken Ecke und gehe von rechts nach links. Am Ende der Reihe gehe ich eine Reihe runter und beginne wieder links. Ich habe ein 240 m Raster mit 2603 Spalten und 2438 Zeilen, also insgesamt 6111844 Zellen. Ich benutze eine Iteratorvariable und eine while-Schleife. Siehe unten
Ein paar Anmerkungen: 1 - Sie müssen die Koordinaten der Ausdehnung kennen
2 - Mit Punktkoordinaten für Zellenmitte ausführen - Verschieben Sie die Hälfte der Zellengröße von den Ausdehnungswerten
3 - Mein Skript verwendet den Zellenwert, um ein wertspezifisches Raster zu ziehen, und verschiebt dieses Raster dann in die Mitte der ursprünglichen Zelle. Dadurch wird ein Null-Raster hinzugefügt, um die Ausdehnung zu erweitern, bevor ein endgültiges Raster erstellt wird. Dies ist nur ein Beispiel. Hier können Sie Ihre bedingten Anweisungen einfügen (zweite if-Anweisung in der while-Schleife).
4 - In diesem Skript wird davon ausgegangen, dass alle Rasterwerte als Ganzzahlen umgewandelt werden können. Dies bedeutet, dass Sie zuerst die Daten loswerden müssen. Con IsNull.
6 - Ich bin immer noch nicht glücklich damit und arbeite daran, dies vollständig aus arcpy herauszuholen. Ich würde lieber als Numpy-Arrays gecastet und die Mathe dort ausführen und sie dann zu Arc zurückbringen.
quelle
Versuchen Sie es mit IGridTable, ICursor, IRow. Dieses Code-Snippet dient zum Aktualisieren von Rasterzellenwerten. Es zeigt jedoch die Grundlagen der Iteration:
Wie kann ich ein neues Feld in eine Rasterattributtabelle einfügen und diese durchlaufen?
Sobald Sie die Tabelle durchlaufen haben, können Sie den spezifischen Feldzeilenwert mit abrufen
row.get_Value(yourfieldIndex)
. Wenn Sie GoogleSie sollten in der Lage sein, viele Beispiele zu bekommen, die dies zeigen.
Ich hoffe, das hilft.
quelle
Wie wäre es damit als radikale Idee, Sie müssten in Python oder ArcObjects programmieren.
quelle
Eine Lösung:
Ich habe das heute früher gelöst. Der Code ist eine Anpassung dieser Methode . Das Konzept dahinter war nicht sonderlich schwierig, als ich herausgefunden hatte, was die Objekte, die für die Schnittstelle zum Raster verwendet wurden, tatsächlich tun. Die folgende Methode verwendet zwei Eingabedatensätze (inRasterDS und outRasterDS). Sie sind beide der gleiche Datensatz. Ich habe gerade eine Kopie von inRasterDS erstellt und sie als outRasterDS an die Methode übergeben. Auf diese Weise haben beide dieselbe Ausdehnung, denselben Raumbezug usw. Die Methode liest die Werte aus inRasterDS Zelle für Zelle und vergleicht sie mit den nächsten Nachbarn. Die Ergebnisse dieser Vergleiche werden als gespeicherte Werte in outRasterDS verwendet.
Der Prozess:
Ich habe IRasterCursor -> IPixelBlock -> SafeArray verwendet, um die Pixelwerte zu ermitteln, und IRasterEdit, um neue Werte in das Raster zu schreiben. Wenn Sie IPixelBlock erstellen, teilen Sie dem Gerät die Größe und Position des Bereichs mit, in den Sie lesen / schreiben möchten. Wenn Sie nur die untere Hälfte eines Rasters bearbeiten möchten, legen Sie dies als IPixelBlock-Parameter fest. Wenn Sie das gesamte Raster durchlaufen möchten, müssen Sie IPixelBlock auf die Größe des gesamten Rasters einstellen. In der folgenden Methode übergebe ich dazu die Größe an IRasterCursor (pSize) und erhalte dann den PixelBlock vom Rastercursor.
Der andere Schlüssel ist, dass Sie SafeArray verwenden müssen, um mit den Werten in dieser Methode zu kommunizieren. Sie erhalten IPixelBlock von IRasterCursor, dann SafeArray von IPixelBlock. Dann lesen und schreiben Sie an SafeArray. Wenn Sie mit dem Lesen / Schreiben in SafeArray fertig sind, schreiben Sie Ihr gesamtes SafeArray zurück in IPixelBlock, schreiben Sie dann Ihren IPixelBlock in IRasterCursor und verwenden Sie schließlich IRasterCursor, um den Speicherort für den Start des Schreibvorgangs festzulegen und IRasterEdit, um den Schreibvorgang selbst durchzuführen. In diesem letzten Schritt bearbeiten Sie die Werte des Datensatzes.
quelle
AFAIK-Rasterdaten können auf drei Arten gelesen werden:
Ohne das Rad neu zu erfinden, empfehle ich, diese aufschlussreichen Folien zu lesen von Chris Garrard .
Die effizienteste Methode ist also das blockweise Lesen von Daten. Dies würde jedoch zu einem Datenverlust bei der Entsprechung von Pixeln führen, die sich während der Anwendung des Filters über den Blockgrenzen befinden. Eine sichere Alternative sollte also darin bestehen, das gesamte Bild auf einmal zu lesen und den Numpy-Ansatz zu verwenden.
Auf der Rechnerseite sollte ich stattdessen gdalfilter.py und implizit den VRT KernelFilteredSource-Ansatz verwenden, um die erforderlichen Filter anzuwenden und vor allem schwere Berechnungen zu vermeiden.
quelle