Trovare posizioni con i valori più alti in raster usando ArcGIS Desktop?


12

Usando ArcGIS 10, ho un raster in cui vorrei trovare il pixel con il valore massimo nel raster e restituire la sua posizione (centro del pixel) in gradi decimali. Vorrei scorrere questo processo restituendo la posizione del secondo valore più alto del raster, quindi il terzo e così via in modo che alla fine ho un elenco di N posizioni che hanno i valori più alti nel raster in ordine.

Immagino che questo potrebbe essere fatto più facilmente usando uno script Python, ma sono aperto ad altre idee se c'è un modo migliore.


hai provato a convertire la griglia in punti quindi ad aggiungere i campi X, Y e l'ordinamento?
Jakub Sisak GeoGraphics,

I valori raster sono float o interi?
whuber

@Jakub - No, non l'ho fatto. Probabilmente sarò interessato solo all'1% circa dei punti, quindi non so se valga la pena aggiungere i campi x, y per tutti i punti e poi l'ordinamento. Forse se non c'è un'opzione più efficiente?
mga

@whuber - I valori raster sono float.
mga

@mga, vale la pena provare. La conversione è abbastanza veloce e l'aggiunta di XY è anche uno strumento predefinito. L'eliminazione di record indesiderati è un'operazione semplice e tutto può essere raggruppato in un singolo modello. Solo un'idea
Jakub Sisak GeoGraphics,

Risposte:


5

Se sei felice di usare R , c'è un pacchetto chiamato raster . Puoi leggere in un raster usando il comando seguente:

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

Quindi, quando vai a guardarlo (digitando test), puoi vedere le seguenti informazioni:

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 

Potrebbero esserci modi migliori per manipolare il raster, ma un modo per trovare le informazioni che desideri potrebbe essere quello di trovare il valore più alto, ottenere la sua posizione della matrice e quindi aggiungerlo all'estensione inferiore.


1
+1 Per questo riferimento. Dopo aver letto il raster R, è possibile utilizzare le Rfunzioni standard o il getValuesmetodo per accedere ai valori delle celle. Da lì è semplice identificare i valori più alti e le loro posizioni.
whuber

1
Grazie alla tua raccomandazione questo è quello che ho finito per fare. L'uso del pacchetto raster in R è stato un gioco da ragazzi rispetto a provare questo in ArcGIS. Ho anche continuato ad usare altre analisi spaziali in R e sono stato molto contento dei risultati. Ottimo consiglio!
mga

8

La risposta può essere ottenuto da combinando una griglia indicatore della parte superiore 1% di valori con griglie di latitudine e longitudine. Il trucco sta nel creare questa griglia di indicatori, perché ArcGIS (ancora! Dopo 40 anni!) Non ha una procedura per classificare i dati raster.

Una soluzione per i raster a virgola mobile è iterativa, ma misericordiosamente rapida . Sia n il numero di celle di dati. La distribuzione cumulativa empirica dei valori è costituita da tutte le coppie (z, n (z)) in cui z è un valore nella griglia e n (z) è il numero di celle nella griglia con valori inferiori o uguali a z . Otteniamo una curva che collega (-infinito, 0) a (+ infinito, n) fuori dalla sequenza di questi vertici ordinati per z . Definisce quindi una funzione f , dove (z, f (z)) si trova sempre sulla curva. Vuoi trovare un punto (z0, 0.99 * n) su questa curva.

In altre parole, il compito è trovare uno zero di f (z) - (1-0.01) * n . Fallo con qualsiasi routine di ricerca zero (in grado di gestire funzioni arbitrarie: questa non è differenziabile). Il più semplice, che spesso è efficiente, è indovinare e controllare: inizialmente sai che z0 si trova tra il valore minimo zMin e il massimo zMax. Indovina qualsiasi valore ragionevole rigorosamente tra questi due. Se l'ipotesi è troppo bassa, impostare zMin = z0; altrimenti imposta zMax = z0. Ora ripeti. Convergerai rapidamente alla soluzione; sei abbastanza vicino quando zMax e zMin sono sufficientemente vicini. Per essere prudenti, scegli il valore finale di zMin come soluzione: potrebbe raccogliere alcuni punti extra che puoi scartare in seguito. Per approcci più sofisticati, consultare il capitolo 9 delle Ricette numeriche (il collegamento passa a una versione gratuita precedente).

Guardando indietro a questo algoritmo si rivela che è necessario eseguire solo due tipi di operazioni raster : (1) selezionare tutte le celle inferiori o uguali a un valore target e (2) contare le celle selezionate. Quelle sono tra le operazioni più semplici e veloci in circolazione. (2) può essere ottenuto come conteggio zonale o leggendo un record dalla tabella degli attributi della griglia di selezione.


7

L'ho fatto qualche tempo fa, anche se la mia soluzione sta usando GDAL (quindi, questo non è solo per ArcGIS). Penso che puoi ottenere un array NumPy da un raster in ArcGIS 10, ma non lo so per certo. NumPy fornisce indicizzazione di array semplice e potente, come argsorte altro. Questo esempio non gestisce NODATA né trasforma le coordinate da proiettate a lat / long (ma questo non è difficile da fare con osgeo.osr, fornito con 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]))

Mostra quanto segue per il mio file raster di prova:

[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

+1 Grazie per averlo condiviso. Non vedo l'impossibilità di gestire NoData come una limitazione: basta convertire tutti i NoData in valori estremamente negativi prima di procedere. Si noti inoltre che se si verifica una riproiezione della griglia , le risposte probabilmente cambieranno a causa del ricampionamento della griglia, quindi normalmente non si desidera che la riproiezione avvenga automaticamente durante un calcolo come questo. Invece, le coordinate riportate possono essere riproiettate in seguito. Quindi la tua soluzione è perfettamente generale.
whuber

La gestione NODATA può essere implementata ottenendo prima il valore dal raster NODATA = rast_band.GetNoDataValue(), quindi utilizzando un valore NaN ( rast[rast == NODATA] = np.nan) o utilizzando un array mascherato ( rast = np.ma.array(rast, mask=(rast == NODATA))). Il trucco più complicato è argsortriuscire a rimuovere in qualche modo i valori NODATA dall'analisi o semplicemente saltarli nel for-loop se sono NaN / mascherati.
Mike T
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.