Come bufferizzare i pixel raster in base ai loro valori?


28

I pixel a sinistra rappresentano le posizioni dell'albero e i raggi della corona associati (ovvero i valori dei pixel vanno da 2 a 5). Vorrei bufferizzare questi pixel raster per il loro valore del raggio della corona. L'immagine a destra è ciò che spero di ottenere utilizzando solo metodi di elaborazione raster .

Inizialmente penserei di utilizzare una somma focale circolare in ArcGIS, sebbene l'impostazione del vicinato sia un valore fisso, che non prenderebbe in considerazione il raggio della corona di dimensioni variabili.

Qual è un buon metodo per "bufferizzare" i pixel in base ai loro valori?

inserisci qui la descrizione dell'immagine


2
Hai provato a convertire raster in punti, quindi buffer per campo e poi riconvertire in raster?

2
Aiuta a rendersi conto che si tratta di un'operazione non locale , poiché quella non località mostra che esistono limiti intrinseci su come eseguire il calcolo. Ad esempio, l'output cambierebbe radicalmente quasi ovunque se solo un singolo pixel isolato nell'input dovesse cambiare in un valore elevato. Pertanto, se si conoscono restrizioni sui valori di input, condividerli, perché ciò può portare a soluzioni migliorate. Ad esempio, tutti i valori di input saranno sempre nel set {2,3,4}?
whuber

@Dan Patterson Ecco come mi è venuta in mente l'immagine a destra. Tuttavia, sto cercando di evitare del tutto le operazioni vettoriali ed evitare quei passaggi.
Aaron

2
@whuber Questo set di dati rappresenta alberi con diametri di corona variabili. Detto questo, le misure del raggio della corona dell'albero possono realisticamente variare da 1 a 10. Vorrei anche aggiungere che l'uscita bufferizzata deve essere solo 0 per l'assenza della corona e 1 per la presenza della corona.
Aaron

1
Ok grazie. Sembra che tu abbia creato l'output di esempio unendo i 3 buffer dei punti con il valore 3, i 4 buffer dei punti con il valore 4 e i 5 buffer dei punti con il valore 5. (Sembra che tu abbia dimenticato per elaborare i punti con valore 2.) Questo processo non solo risponde alla tua domanda, ma (credo) è la soluzione più semplice usando gli strumenti disponibili in Spatial Analyst.
whuber

Risposte:


14

Ecco una soluzione raster pura Python 2.7nell'uso numpye scipy:

import numpy as np
from scipy import ndimage
import matplotlib.pyplot as plt

#create tree location matrix with values indicating crown radius
A = np.zeros((120,320))
A[60,40] = 1
A[60,80] = 2
A[60,120] = 3
A[60,160] = 4
A[60,200] = 5
A[60,240] = 6
A[60,280] = 7

#plot tree locations
fig = plt.figure()
plt.imshow(A, interpolation='none')
plt.colorbar()

#find unique values
unique_vals = np.unique(A)
unique_vals = unique_vals[unique_vals > 0]

# create circular kernel
def createKernel(radius):
    kernel = np.zeros((2*radius+1, 2*radius+1))
    y,x = np.ogrid[-radius:radius+1, -radius:radius+1]
    mask = x**2 + y**2 <= radius**2
    kernel[mask] = 1
    return kernel

#apply binary dilation sequentially to each unique crown radius value 
C = np.zeros(A.shape).astype(bool)   
for k, radius in enumerate(unique_vals):  
    B = ndimage.morphology.binary_dilation(A == unique_vals[k], structure=createKernel(radius))
    C = C | B #combine masks

#plot resulting mask   
fig = plt.figure()
plt.imshow(C, interpolation='none')
plt.show()

Ingresso: inserisci qui la descrizione dell'immagine

Produzione: inserisci qui la descrizione dell'immagine


1
+1 per l'approccio di dilatazione! Funziona anche con punti vicini.
Antonio Falciano,

Questo è un ottimo esempio del perché quel vecchio jet color fosse terribile. Questo sembra molto più chiaro con viridis.
naught101

8

Approccio basato su vettori

Questa attività può essere eseguita in tre passaggi:

Nota: l'utilizzo del campo buffer evita il calcolo di un buffer per ciascun valore del raggio della corona.


Approccio basato su raster

Evitando la soluzione basata su vettori, questo problema suggerisce di utilizzare una specie di automi cellulari basati sui vicini più vicini. Supponendo che tutti i pixel neri siano zeri, i pixel siano quadrati e la loro dimensione sia uguale a 1 (o, in alternativa, siano opportunamente ridimensionati), le regole da adottare sono molto semplici:

  1. Se il valore del pixel ( VALUE) è maggiore di 1, il suo valore diventa VALUE-1e quindi considera i pixel circostanti. Se i loro valori sono inferiori a VALUE-1, questi pixel nascono o crescono e il loro valore diventa VALUE-1. Altrimenti, questi pixel sopravvivono e rimangono invariati.
  2. Se VALUE<=1non fai nulla (il pixel è morto!).

Queste regole devono essere applicate fino a quando tutti i pixel non sono morti, ovvero i loro valori sono uguali a 0 o 1. Quindi N-1, volte, dov'è Nil valore massimo che hai nell'input raster. Questo approccio può essere facilmente implementato con un po 'di Python e numpy.


1
Grazie per la risposta afalciano. Questo metodo è il modo in cui ho creato l'immagine a destra e utilizza un approccio vettoriale, uno che sto cercando di evitare.
Aaron

1
Ok Aaron, ecco un approccio basato sul raster ora. Spero che sia di aiuto.
Antonio Falciano,

7

Un'altra opzione sarebbe quella di creare raster separati per ciascun valore di pixel, in questo caso 4 raster, con una condizione. Quindi espandere i raster di un numero di pixel corrispondente al valore del raster (eventualmente ripetendo un elenco di valori). Infine, unisciti ai raster (algebrici o spazialmente), per creare un raster binario per le corone degli alberi.


1
Questa idea è quella giusta. I dettagli possono essere migliorati: (1) la selezione crea un indicatore binario (0,1) degli alberi di un dato raggio della corona. (2) Una somma focale di quella selezione - usando una vicinanza circolare del raggio dato - è veloce da calcolare usando la FFT. (3) Aggiungendo le somme focali (in senso puntuale) e confrontandolo con 0 si ottiene il buffer desiderato.
whuber

7

È una domanda difficile farlo in raster perché non hai l'opportunità di usare il valore del pixel per definire la dimensione del buffer. Pertanto, è necessario fare il filtro focale per ciascun valore, come già detto.

Ecco una possibile risposta per farlo con solo 3 filtri (non riuscivo a trovarne di meno), ma non perfettamente come menzionato da Whuber: i tuoi buffer verranno troncati quando gli alberi si avvicinano.

1) EDIT: allocazione euclidea (questo non risolve completamente il problema, poiché taglia i buffer in prossimità di alberi più piccoli, ma è meglio dei manufatti della mia prima soluzione).

2) distanza euclidea attorno a ciascun pixel

3) calcolatrice raster (mappa algebra) con una dichiarazione condizionale

Con("allocation_result" > ("distance_result" / pixel_size) , 1 , 0)

Si noti che è possibile regolare la condizione in base alle proprie esigenze in termini di raggio (con o senza pixel centrale)


+1 Questo è un approccio creativo. Proverò a vedere se è possibile ridimensionare usando questo approccio.
Aaron

2
L'approccio della distanza euclidea non funzionerà, perché calcola solo la distanza dall'albero più vicino , che non è necessariamente la distanza da un albero la cui corona copre il punto.
whuber

2

Ti chiedi perché non usi lo strumento di espansione di ArcGIS ?

import arcpy
from arcpy.sa import *

raster_in  = r'c:\test.tif'
raster_out = r'c:\test_out.tif'

outExpand1 = Expand(raster_in, 2, 2)
outExpand2 = Expand(outExpand1, 3, 3)
outExpand3 = Expand(outExpand3, 4, 4)
outExpand4 = Expand(outExpand4, 5, 5)

outExpand4.save(raster_out)

In caso di sovrapposizione: l'ultimo expandcomando coprirà quelli precedenti.


2

Se hai la posizione dei pixel, il raggio e l' algoritmo del cerchio del punto medio (una variante di Bresenham Alg.) Ti danno un indizio. IMO è facile creare un poligono da questo approccio e penso che sia facile implementarlo in Python. Un'unione di questo set di poligoni ti dà l'area di copertura.


So che non è una questione di domanda, ma vuoi saperne di più sulle primitive grafiche e sul riempimento poligonale delle linee di scansione? Per i cirles è molto semplice. La combinazione convessa è una parola d'ordine e così via ....
huckfinn,

Come verrebbe applicato utilizzando le operazioni raster di base?
whuber

Se provi a gestirlo nello spazio raster, determina i punti del cerchio, ordinandoli per y o xe riempi lo spazio con una linea retta (linea di scansione) per riempire il cerchio. Nell'approccio triangolare, se si costruisce il cerchio mediante un'approssimazione di settori tringolari e si tenta di riempire il triangolo, è necessario un test se il punto è interno o esterno (combinazione convessa) ed è l'altro modo. E nell'approccio "GIS", la costruzione di poligoni (poligoni orientati all'orologio) e la creazione di un'unione è la terza (IMO la più costosa in termini di calcolo).
huckfinn,

Per essere chiari: E nell'approccio "GIS" ... effettuare un'operazione algebrarica come unione, intersezione, tocco .... è la terza IMO la più costosa e computuale.
huckfinn,
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.