Voir ce lien pour plus de détails.
Le problème:
Je veux parcourir un raster continu (un qui n'a pas de table attributaire), cellule par cellule, et obtenir la valeur de la cellule. Je veux prendre ces valeurs et exécuter des conditions dessus, en émulant les étapes d'algèbre de carte détaillées ci-dessous sans réellement utiliser la calculatrice raster.
Par demande de commentaires ci-dessous, j'ai ajouté des détails fournissant un contexte au problème et justifiant la nécessité de mettre en œuvre une méthode en tant que telle dans la section ci-dessous intitulée "L'analyse nécessaire:".
L'analyse proposée ci-dessous, tout en étant pertinente pour mon problème en fournissant un contexte, n'a pas besoin d'être implémentée dans une réponse. La portée de la question ne concerne que l'itération à travers un raster continu pour obtenir / définir les valeurs des cellules.
L'analyse avait besoin:
Si TOUTES les conditions suivantes sont remplies, donnez à la cellule de sortie une valeur de 1. Ne donnez à la cellule de sortie une valeur de 0 que si aucune des conditions n'est remplie.
Condition 1: si la valeur de la cellule est supérieure aux cellules supérieure et inférieure, donnez la valeur 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Où le fichier noyau ressemble à ceci:
3 3
0 1 0
0 0 0
0 1 0
Condition 2: si la valeur de la cellule est supérieure aux cellules gauche et droite, donnez la valeur 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Où le fichier noyau ressemble à ceci:
3 3
0 0 0
1 0 1
0 0 0
Condition 3: si la valeur de la cellule est supérieure aux cellules de gauche et de droite, donnez la valeur 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Où le fichier noyau ressemble à ceci:
3 3
1 0 0
0 0 0
0 0 1
Condition 4: si la valeur de la cellule est supérieure aux cellules de gauche et de droite, donnez la valeur 1:
Con("raster" > FocalStatistics("raster", NbrIrregular("C:\filepath\kernel_file.txt"), "MAXIMUM"), 1, 0)
Où le fichier noyau ressemble à ceci:
3 3
0 0 1
0 0 0
1 0 0
Condition 5: si l' une des cellules adjacentes a une valeur ÉGALE à la cellule centrale, donnez au raster en sortie une valeur de 1 (en utilisant la variété focale avec deux calculs de voisinage les plus proches )
Pourquoi ne pas utiliser l'algèbre cartographique?
Il a été noté ci-dessous que mon problème pourrait être résolu en utilisant l'algèbre de la carte, mais comme vu ci-dessus, il s'agit d'un total de six calculs raster, plus un pour combiner tous les rasters créés ensemble. Il me semble qu'il est beaucoup plus efficace de procéder cellule par cellule et de faire toutes les comparaisons à la fois dans chaque cellule au lieu de parcourir sept fois individuellement et d'utiliser beaucoup de mémoire pour créer sept rasters.
Comment le problème doit-il être attaqué?
Le lien ci-dessus conseille d'utiliser l'interface IPixelBlock, mais il n'est pas clair dans la documentation ESRI si vous accédez réellement à une seule valeur de cellule via IPixelBlock, ou si vous accédez à plusieurs valeurs de cellule à partir de la taille de l'IPixelBlock que vous définissez. Une bonne réponse devrait suggérer une méthode pour accéder aux valeurs de cellule d'un raster continu et fournir une explication de la méthodologie derrière le code, si ce n'est apparemment évident.
En résumé:
Quelle est la meilleure méthode pour parcourir chaque cellule d'un raster CONTINU (qui n'a pas de table attributaire ) pour accéder à ses valeurs de cellule?
Une bonne réponse n'a pas besoin de mettre en œuvre les étapes d'analyse décrites ci-dessus, il suffit de fournir une méthodologie pour accéder aux valeurs de cellule d'un raster.
Réponses:
Je vois que cela a déjà été résolu par l'affiche originale (OP), mais je publierai une solution simple en python au cas où quelqu'un à l'avenir serait intéressé par différentes manières de résoudre ce problème. Je suis amateur de logiciels open source, voici donc une solution utilisant GDAL en python:
Implémentez la fonction comme ceci:
Ensuite, parcourez vos données avec une boucle imbriquée:
Ou peut-être souhaitez-vous aplatir votre réseau 2D avec une compréhension de liste:
Quoi qu'il en soit, tout en parcourant les données cellule par cellule, il est possible de jeter des conditions dans votre boucle pour modifier / modifier les valeurs. Voir ce script que j'ai écrit pour différentes façons d'accéder aux données: https://github.com/azgs/hazards-viewer/blob/master/python/zonal_stats.py .
la source
Mise à jour! La solution numpy:
Il est donc difficile de remettre le tableau fini sur le raster à l'aide d'arcpy. arcpy.NumPyArrayToRaster est écureuil et a tendance à redéfinir les étendues même si vous lui donnez vos coordonnées LL.
Je préfère enregistrer en tant que texte.
J'utilise Python en 64 bits pour la vitesse - en ce moment, cela signifie que je ne peux pas nourrir numpy.savetxt un en-tête. Je dois donc ouvrir la sortie et ajouter l'en-tête ASCII que Arc veut avant de convertir ASCII en Raster
La version numpy exécute mon raster shift, mes multiplications et mes ajouts beaucoup plus rapidement (1000 itérations en 2 minutes) que la version arcpy (1000 itérations en 15 min)
ANCIENNE VERSION Je peux supprimer cela plus tard, je viens d'écrire un script similaire. J'ai essayé de convertir en points et d'utiliser le curseur de recherche. J'ai obtenu seulement 5000 itérations en 12 heures. J'ai donc cherché une autre voie.
Ma façon de procéder consiste à parcourir les coordonnées du centre de chaque cellule. Je commence dans le coin supérieur gauche et me déplace de droite à gauche. À la fin du rang, je descends d'un rang et recommence à gauche. J'ai un raster de 240 m avec 2603 colonnes et 2438 lignes donc un total de 6111844 cellules au total. J'utilise une variable itérateur et une boucle while. Voir ci-dessous
Quelques notes: 1 - vous devez connaître les coordonnées de l'étendue
2 - exécuter avec les coordonnées du point pour le centre de la cellule - déplacer de la moitié de la taille de la cellule à partir des valeurs d'étendue
3 - Mon script utilise la valeur de cellule pour extraire un raster spécifique à une valeur, puis décaler ce raster pour le centrer sur la cellule d'origine. Cela ajoute à un raster zéro pour étendre l'étendue avant de l'ajouter à un raster final. C'est juste un exemple. Vous pouvez mettre vos instructions conditionnelles ici (deuxième instruction if dans la boucle while).
4 - Ce script suppose que toutes les valeurs raster peuvent être converties en entiers. Cela signifie que vous devez d'abord vous débarrasser de l'absence de données. Con IsNull.
6 - Je ne suis toujours pas satisfait de cela et je travaille pour le supprimer complètement d'Arcpy. Je préfère lancer des tableaux numpy et faire le calcul là-bas, puis le ramener à Arc.
la source
Essayez d'utiliser IGridTable, ICursor, IRow. Cet extrait de code sert à mettre à jour les valeurs des cellules raster, mais il montre les bases de l'itération:
Comment puis-je ajouter un nouveau champ dans une table attributaire raster et le parcourir?
Une fois que vous parcourez la table, vous pouvez obtenir la valeur de ligne de champ spécifique en utilisant
row.get_Value(yourfieldIndex)
. Si vous Googlevous devriez pouvoir obtenir de nombreux exemples le montrant.
J'espère que cela pourra aider.
la source
Que diriez-vous d'une idée radicale, cela nécessiterait que vous programmiez en python ou ArcObjects.
la source
Une solution:
J'ai résolu cela plus tôt dans la journée. Le code est une adaptation de cette méthode . Le concept derrière cela n'a pas été terriblement difficile une fois que j'ai compris ce que les objets utilisés pour interfacer avec le raster font réellement. La méthode ci-dessous prend deux jeux de données d'entrée (inRasterDS et outRasterDS). Ils sont tous deux le même ensemble de données, je viens de faire une copie de inRasterDS et de le passer dans la méthode en tant que outRasterDS. De cette façon, ils ont tous deux la même étendue, la même référence spatiale, etc. La méthode lit les valeurs dans inRasterDS, cellule par cellule, et effectue des comparaisons avec les voisins les plus proches. Il utilise les résultats de ces comparaisons comme valeurs stockées dans outRasterDS.
Le processus:
J'ai utilisé IRasterCursor -> IPixelBlock -> SafeArray pour obtenir les valeurs en pixels et IRasterEdit pour en écrire de nouvelles dans le raster. Lorsque vous créez IPixelBlock, vous indiquez à la machine la taille et l'emplacement de la zone dans laquelle vous souhaitez lire / écrire. Si vous souhaitez uniquement modifier la moitié inférieure d'un raster, vous le définissez comme vos paramètres IPixelBlock. Si vous souhaitez boucler sur l'ensemble du raster, vous devez définir IPixelBlock égal à la taille de l'ensemble du raster. Je fais cela dans la méthode ci-dessous en passant la taille à IRasterCursor (pSize) puis en obtenant le PixelBlock du curseur raster.
L'autre clé est que vous devez utiliser SafeArray pour interfacer avec les valeurs de cette méthode. Vous obtenez IPixelBlock d'IRasterCursor, puis SafeArray d'IPixelBlock. Ensuite, vous lisez et écrivez dans SafeArray. Lorsque vous avez terminé la lecture / écriture sur SafeArray, réécrivez l'intégralité de votre SafeArray sur IPixelBlock, puis écrivez votre IPixelBlock sur IRasterCursor, puis utilisez enfin IRasterCursor pour définir l'emplacement de démarrage de l'écriture et IRasterEdit pour effectuer l'écriture elle-même. Cette dernière étape est l'endroit où vous modifiez réellement les valeurs de l'ensemble de données.
la source
Les données raster AFAIK peuvent être lues de trois manières:
Sans réinventer la roue, je vous propose de lire ces diapositives éclairantes de Chris Garrard.
Ainsi, la méthode la plus efficace consiste à lire les données par bloc, mais cela entraînerait une perte de données dans la correspondance des pixels situés sur les limites du bloc lors de l'application du filtre. Une autre solution sûre devrait donc consister à lire l'image entière en une seule fois et à utiliser l'approche numpy.
Du côté informatique, je devrais plutôt utiliser gdalfilter.py et implicitement l'approche VRT KernelFilteredSource afin d'appliquer les filtres nécessaires et, surtout, d'éviter les calculs lourds.
la source