Trouver les emplacements des valeurs les plus élevées dans le raster à l'aide d'ArcGIS Desktop?

12

En utilisant ArcGIS 10, j'ai un raster où je voudrais trouver le pixel avec la valeur maximale dans le raster et retourner son emplacement (centre du pixel) en degrés décimaux. Je voudrais répéter ce processus en renvoyant l'emplacement de la deuxième valeur la plus élevée du raster, puis la troisième, et ainsi de suite de sorte qu'à la fin, j'ai une liste de N emplacements qui ont les valeurs les plus élevées dans le raster dans l'ordre.

J'imagine que cela pourrait être plus facilement fait en utilisant un script Python mais je suis ouvert à d'autres idées s'il y a une meilleure façon.

mga
la source
avez-vous essayé de convertir la grille en points, puis d'ajouter des champs X, Y et de trier?
Jakub Sisak GeoGraphics
Les valeurs raster sont-elles flottantes ou entières?
whuber
@Jakub - Non, je ne l'ai pas fait. Je ne serai probablement intéressé que par les 1% ou plus de points, donc je ne sais pas si cela vaut la peine d'ajouter des champs x, y pour tous les points, puis de les trier. Peut-être s'il n'y a pas d'option plus efficace?
mga
@whuber - Les valeurs raster sont des flottants.
mga
@mga, ça vaut le coup d'essayer. La conversion est assez rapide et l'ajout du XY est également un outil par défaut. La suppression d'enregistrements indésirables est une opération simple et tous peuvent être regroupés dans un seul modèle. Juste une idée.
Jakub Sisak GeoGraphics

Réponses:

5

Si vous êtes heureux d'utiliser R , il existe un package appelé raster . Vous pouvez lire dans un raster à l'aide de la commande suivante:

install.packages('raster')
library(raster)
test <- raster('F:/myraster')

Ensuite, lorsque vous allez le regarder (en tapant test), vous pouvez voir les informations suivantes:

class       : RasterLayer 
dimensions  : 494, 427, 210938  (nrow, ncol, ncell)
resolution  : 200, 200  (x, y)
extent      : 1022155, 1107555, 1220237, 1319037  (xmin, xmax, ymin, ymax)
coord. ref. : +proj=aea +lat_1=29.5 +lat_2=45.5 +lat_0=23 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs +towgs84=0,0,0 
values      : F:/myraster 
min value   : 0 
max value   : 1 

Il peut y avoir de meilleures façons de manipuler le raster, mais une façon de trouver les informations que vous souhaitez pourrait être de trouver la valeur la plus élevée, d'obtenir son emplacement de matrice, puis d'ajouter cela aux extensions inférieures.

djq
la source
1
+1 Pour cette référence. Une fois que vous avez lu le raster R, vous pouvez utiliser des Rfonctions standard ou la getValuesméthode pour accéder aux valeurs des cellules. De là, il est simple d'identifier les valeurs les plus élevées et leurs emplacements.
whuber
1
Grâce à votre recommandation, c'est ce que j'ai fini par faire. L'utilisation du package raster dans R a été un jeu d'enfant par rapport à l'essai dans ArcGIS. J'ai également continué à utiliser d'autres analyses spatiales dans R et j'ai été très satisfait des résultats. Très bon conseil!
mga
8

La réponse peut être obtenue en combinant une grille indicatrice du 1% supérieur de valeurs avec des grilles de latitude et de longitude. L'astuce consiste à créer cette grille d'indicateurs, car ArcGIS (toujours! Après 40 ans!) N'a pas de procédure pour classer les données raster.

Une solution pour les rasters à virgule flottante est itérative, mais heureusement rapide . Soit n le nombre de cellules de données. La distribution empirique cumulative des valeurs se compose de toutes les paires (z, n (z)) où z est une valeur dans la grille et n (z) est le nombre de cellules dans la grille avec des valeurs inférieures ou égales à z . Nous obtenons une courbe reliant (-infinity, 0) à (+ infinity, n) à partir de la séquence de ces sommets ordonnée par z . Il définit ainsi une fonction f , où (z, f (z)) se trouve toujours sur la courbe. Vous voulez trouver un point (z0, 0.99 * n) sur cette courbe.

En d'autres termes, la tâche consiste à trouver un zéro de f (z) - (1-0.01) * n . Faites-le avec n'importe quelle routine de recherche de zéro (qui peut gérer des fonctions arbitraires: celle-ci n'est pas différenciable). Le plus simple, qui est souvent efficace, est de deviner et de vérifier: au départ, vous savez que z0 se situe entre la valeur minimale zMin et la valeur maximale zMax. Devinez toute valeur raisonnable strictement entre ces deux. Si la supposition est trop faible, définissez zMin = z0; sinon définissez zMax = z0. Maintenant, répétez. Vous convergerez rapidement vers la solution; vous êtes suffisamment proche lorsque zMax et zMin sont suffisamment proches. Pour être prudent, choisissez la valeur finale de zMin comme solution: il pourrait ramasser quelques points supplémentaires que vous pourrez supprimer plus tard. Pour des approches plus sophistiquées, voir le chapitre 9 des recettes numériques (le lien va vers une ancienne version gratuite).

Un examen rétrospectif de cet algorithme révèle que vous devez effectuer uniquement deux types d'opérations raster : (1) sélectionner toutes les cellules inférieures ou égales à une valeur cible et (2) compter les cellules sélectionnées. Ce sont parmi les opérations les plus simples et les plus rapides du marché. (2) peut être obtenu sous la forme d'un comptage zonal ou en lisant un enregistrement de la table attributaire de la grille de sélection.

whuber
la source
7

Je l'ai fait il y a quelque temps, bien que ma solution utilise GDAL (donc ce n'est pas seulement pour ArcGIS). Je pense que vous pouvez obtenir un tableau NumPy à partir d'un raster dans ArcGIS 10, mais je ne suis pas sûr. NumPy fournit une indexation de tableau simple et puissante, comme argsortet d'autres. Cet exemple ne gère pas NODATA ni ne transforme les coordonnées du projeté en lat / long (mais ce n'est pas difficile à faire avec osgeo.osr, fourni avec GDAL)

import numpy as np
from osgeo import gdal

# Open raster file, and get GeoTransform
rast_src = gdal.Open(rast_fname)
rast_gt = rast_src.GetGeoTransform()

def get_xy(r, c):
    '''Get (x, y) raster centre coordinate at row, column'''
    x0, dx, rx, y0, ry, dy = rast_gt
    return(x0 + r*dx + dx/2.0, y0 + c*dy + dy/2.0)

# Get first raster band
rast_band = rast_src.GetRasterBand(1)

# Retrieve as NumPy array to do the serious work
rast = rast_band.ReadAsArray()

# Sort raster pixels from highest to lowest
sorted_ind = rast.argsort(axis=None)[::-1]

# Show highest top 10 values
for ind in sorted_ind[:10]:
    # Get row, column for index
    r, c = np.unravel_index(ind, rast.shape)
    # Get [projected] X and Y coordinates
    x, y = get_xy(r, c)
    print('[%3i, %3i] (%.3f, %.3f) = %.3f'%
          (r, c, x, y, rast[r, c]))

Affiche les éléments suivants pour mon fichier raster de test:

[467, 169] (2813700.000, 6353100.000) = 844.538
[467, 168] (2813700.000, 6353200.000) = 841.067
[469, 168] (2813900.000, 6353200.000) = 840.705
[468, 168] (2813800.000, 6353200.000) = 840.192
[470, 167] (2814000.000, 6353300.000) = 837.063
[468, 169] (2813800.000, 6353100.000) = 837.063
[482, 166] (2815200.000, 6353400.000) = 833.038
[469, 167] (2813900.000, 6353300.000) = 832.825
[451, 181] (2812100.000, 6351900.000) = 828.064
[469, 169] (2813900.000, 6353100.000) = 827.514
Mike T
la source
+1 Merci d'avoir partagé cela. Je ne vois pas une incapacité à gérer NoData comme une limitation: il suffit de convertir tous les NoData en valeurs extrêmement négatives avant de continuer. Notez également que si une reprojection de la grille se produit, les réponses changeront probablement en raison du rééchantillonnage de la grille, donc normalement, on ne veut pas que la reprojection se produise automatiquement lors d'un calcul comme celui-ci. Au lieu de cela, les coordonnées signalées peuvent être reprojetées par la suite. Votre solution est donc parfaitement générale.
whuber
La gestion NODATA peut être implémentée en obtenant d'abord la valeur du raster NODATA = rast_band.GetNoDataValue(), puis en utilisant soit une valeur NaN ( rast[rast == NODATA] = np.nan) soit en utilisant un tableau masqué ( rast = np.ma.array(rast, mask=(rast == NODATA))). L'astuce la plus compliquée consiste argsortà supprimer en quelque sorte les valeurs NODATA de l'analyse, ou simplement à les ignorer dans la boucle for si elles sont NaN / masquées.
Mike T