Vous comptez des valeurs de pixels consécutives pour un ensemble de rasters à l'aide d'ArcGIS Spatial Analyst?


23

J'utilise ArcGIS 10 avec Spatial Analyst.

J'ai un ensemble de rasters (8 au total) qui contiennent uniquement un 1 ou un 0 pour chaque cellule. Chaque raster représente des années de données différentes. Pour des raisons d'argument de l'année 1 à l'année 8.

Je peux ajouter tous les rasters ensemble, ce qui me donnera une grille finale avec des valeurs allant de 0 à 8. Un 8 indiquant que la cellule était constamment 1 pour l'ensemble des rasters (toutes les années).

Je voudrais connaître pour chaque cellule le plus long nombre consécutif de 1.

Ainsi, par exemple, la grille totale peut enregistrer pour une seule cellule une valeur de disons 5, mais sur les 8 grilles, cette cellule a le plus grand nombre consécutif de 1 égal à 3. Ou une autre façon d'exprimer cela est pendant 3 ans que la cellule était un 1 puis il a commencé à osciller entre les zéros et les uns.

Mes compétences en traitement de trame ne sont pas aussi chaudes que mes compétences en traitement vectoriel et j'ai bien regardé le fichier d'aide d'ESRI, mais je n'arrive pas à comprendre comment on pourrait y parvenir en utilisant des outils de géotraitement standard?

Des idées?


1
C'est en fait une analyse assez cool. Comme d'habitude, il y a plus d'une façon de faire ce que vous essayez de faire. Je pense que vous devrez faire de la programmation pour parcourir toutes les combinaisons.
MLowry

1
Un commentaire général (inspiré de cette remarque de @MLowry): veuillez voter pour les questions chaque fois qu'elles semblent intéressantes ou clairement articulées. Les bonnes questions animent tout sur notre site; faisons ce que nous pouvons pour récompenser ceux qui les demandent!
whuber

Réponses:


14

Comme il s'agit d'une opération locale, essayons de savoir comment le faire pour une seule cellule: Map Algebra s'occupe du reste.

Notez d'abord que l' ordre des rasters est évidemment important. Par conséquent, les statistiques de cellule à coup unique, comme la somme des cellules, ne le feront pas.

Si nous rencontrions une séquence telle que 01110101 dans une cellule donnée, nous la traiterions du début à la fin et

  1. Commencez par un décompte à zéro.

  2. Augmentez le nombre chaque fois que nous rencontrons un 1.

  3. Réinitialisez le décompte chaque fois que nous rencontrons un 0, après avoir enregistré le dernier décompte .

  4. À la fin, prenez le nombre maximum enregistré (y compris le nombre final).

L'étape 1 est implémentée avec une grille à zéro constant. Les étapes 2 et 3 dépendent de ce que nous rencontrons: il s'agit donc d'une opération conditionnelle . L'étape 4 est clairement un maximum local. Nous coderions alors ceci un peu plus formellement comme:

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

Il est préférable de le faire avec un script Python lorsque vous avez plusieurs grilles, mais avec huit, il n'est pas onéreux de dérouler la boucle et d'écrire les étapes à la main. Cela révèle un léger problème: result=max(longest,count)c'est une sorte d '"effet secondaire" difficile à coder avec les opérations raster. (Mais cela peut être fait, comme indiqué dans la deuxième solution ci-dessous.) Il est également inefficace, car il ajoute un calcul supplémentaire à chaque étape. Nous modifions donc un peu l'approche, dans le but de remettre l' maxopération à terme. Il faudra pour cela enregistrer un décompte séparé à chaque étape.

En passant par ce processus, j'ai également trouvé un raccourci pour la première étape. Cela conduit à la solution suivante, qui, bien qu'un peu longue et gourmande en RAM, est simple et implique des étapes exécutées rapidement:

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")

La syntaxe réelle varie selon votre version d'ArcMap. (Par exemple, CellStatisticsje suis nouveau dans la version 10, mais une opération maximale locale a toujours été disponible.)

Dans l'exemple avec l'entrée 01110101, la séquence de grilles "résultat *" contiendrait les valeurs 0, 1, 2, 3, 0, 1, 0, 1, donc à la fin CellStatisticsretournerait 3, la longueur de la plus longue chaîne de 1.

Si la RAM est rare, la solution peut être modifiée pour réutiliser les résultats intermédiaires, au prix d'un doublement du temps d'exécution:

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"]

Dans l'exemple avec l'entrée 01110101, les valeurs ("temp", "result") seraient (NoData, 0) après la première ligne et après chaque paire d'opérations ("Con", "CellStatistics") les valeurs seraient (1 , 1), (2, 2), (3, 3), (0, 3), (1, 3), (0, 3), (1, 3). Encore une fois, la valeur finale est 3.

Le modèle régulier d'expressions d'algèbre de carte dans l'une ou l'autre solution indique comment coder l'algorithme en boucle dans un script, en changeant les index selon les besoins à chaque itération.


Il pourrait y avoir une faute de frappe dans le bloc de code de type: count = count = 1 devrait probablement être count = count + 1
MLowry

1
@ML Merci (bons yeux!): C'est corrigé maintenant. Il est difficile de rendre le pseudocode absolument correct; l'examen humain est un véritable atout pour détecter les erreurs. De plus, bien que je n'aie pas testé les solutions dans ArcGIS, j'ai implémenté la première solution dans R, j'ai donc une certaine assurance que l'approche est correcte.
whuber

1
"whuber" encore une fois vous êtes l'homme qui sait! Dieu aide le reste d'entre nous si jamais tu te fais écraser par un bus! Votre approche Python initiale était la direction dans laquelle je pensais, mais je sais qu'avec les rasters, on peut souvent tout faire tellement plus lisse que vous avez prouvé. Si vous vous trouvez en Grande-Bretagne, ce serait un honneur de vous acheter une pinte de notre meilleure bière plate à température ambiante! :)
Hornbydd

Merci, Duncan: mais découvrez l'excellente solution d'Andy Harfoot!
whuber

14

Il suffit de discuter de cela et de se demander si vous pouvez aborder le problème en traitant les grilles d'entrée comme un flux binaire. Cela vous permettrait de les combiner pour donner un entier récapitulatif unique pour la séquence - c'est-à-dire 01110101 = 117. Cette valeur pourrait ensuite être reclassée pour donner le nombre maximum de 1 consécutifs.

Voici un exemple montrant une façon de combiner huit grilles:

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

Les opérations au niveau du bit pourraient également être mises en service pour cette étape. Alternativement, vous pouvez utiliser une combinaison suivie d'un calcul de champ. (Le calcul du champ aura une expression similaire à la précédente.)

Le tableau de reclassement doit fournir des longueurs de course maximales pour toutes les valeurs comprises entre 00000000B = 0 et 11111111B = 255. Dans l'ordre, les voici:

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

Cette approche est limitée à environ 20 grilles dans ArcGIS: en utiliser plus peut créer une table d'attributs peu maniable. ( Combineest spécifiquement limité à 20 grilles.)


Un énorme +1: c'est une très bonne idée. (La seule limite est que lorsque plus de 31 grilles sont impliquées, vous manquerez de bits à utiliser.) J'ai pris la liberté de développer un peu votre idée afin que les autres puissent voir à quel point il est facile à mettre en œuvre.
whuber

3

Avez-vous pensé à changer les valeurs de 0 et 1 à des valeurs de puissance 2 (1,2,4,8,16,32). Lorsque vous combinez les 8 grilles, vous obtiendrez des valeurs uniques pour chaque cellule qui vous donneront des informations consécutives (c'est-à-dire: une valeur de 3 signifie les années 1 et 2, où une valeur de 54 serait les années 6 à 8).

Juste une pensée


C'est précisément ce que @Andy Harfoot a suggéré quelques heures plus tôt, Ryan. :-)
whuber

Merci et désolé. Je lis ceci sur mon téléphone en vacances.
Ryan Garnett
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.