Quali strumenti di smoothing / generalizzazione raster sono disponibili?


46

Ho un DEM che vorrei lisciare o generalizzare per rimuovere gli estremi topografici (tagliare i picchi e riempire le valli). Idealmente, vorrei anche avere il controllo del raggio o del livello di "sfocatura". Alla fine, avrò bisogno di un set di raster che vanno da leggermente sfocate a davvero sfocate. (Teoricamente, il più sfocato sarebbe un raster costante della media aritmetica di tutti i valori).

Ci sono strumenti o metodi che posso usare (basato su Esri, GDAL, GRASS)? Devo preparare a casa la mia routine di sfocatura gaussiana ? Potrei usare un filtro passa-basso (ad esempio il filtro ArcGIS ) e, in tal caso, dovrei eseguirlo un sacco di volte per ottenere l'effetto di un ampio raggio?


Che ne dici di esportare il raster in una cella più grande? Ciò non comporterebbe anche un muting degli estremi?

1
Sì, ciò ridurrebbe anche gli estremi (supponendo che il ricampionamento implicito comporti una qualche forma di media) ma è un modo terribile per smussare un DEM: si creerebbe un piccolo numero di blocchi di grandi dimensioni. A proposito, di solito non è necessario esportare un raster per farlo; l'aggregazione e il ricampionamento in una dimensione di cella diversa sono operazioni di base che si trovano di solito nei software basati su raster.
whuber

Risposte:


29

La sfocatura gaussiana è solo una media focale ponderata. Puoi ricrearlo con elevata precisione con una sequenza di mezzi circolari a breve distanza (non ponderati): questa è un'applicazione del Teorema del limite centrale .

Hai molte scelte. "Filtro" è troppo limitato - è solo per 3 x 3 quartieri - quindi non preoccuparti. L'opzione migliore per DEM di grandi dimensioni è quella di portare il calcolo al di fuori di ArcGIS in un ambiente che utilizza trasformazioni di Fourier veloci: eseguono gli stessi calcoli focali ma (in confronto) lo fanno in modo sorprendentemente veloce. (GRASS ha un modulo FFT . È progettato per l'elaborazione delle immagini ma potresti essere in grado di metterlo in servizio per il tuo DEM se riesci a ridimensionarlo con ragionevole precisione nella gamma 0..255.) Tranne che, almeno due soluzioni sono vale la pena considerare:

  1. Crea una serie di pesi di quartiere per approssimare una sfocatura gaussiana per un quartiere considerevole. Usa passaggi successivi di questa sfocatura per creare la tua sequenza di DEM sempre più fluidi.

    (I pesi sono calcolati come exp (-d ^ 2 / (2r)) dove d è la distanza (nelle celle se vuoi) e r è il raggio effettivo (anche nelle celle). Devono essere calcolati all'interno di un cerchio che si estende almeno per 3r . Dopo averlo fatto, dividere ogni peso per la somma di tutti così alla fine si sommano a 1.)

  2. In alternativa, dimenticare la ponderazione; basta eseguire ripetutamente una media focale circolare. Ho fatto esattamente questo per studiare come cambiano le griglie derivate (come pendenza e aspetto) con la risoluzione di un DEM.

Entrambi i metodi funzioneranno bene e dopo i primi passaggi ci sarà poco da scegliere tra i due, ma ci sono rendimenti decrescenti: il raggio effettivo di n mezzi focali successivi (tutti usando la stessa dimensione di vicinato) è solo (approssimativamente) il radice quadrata di n volte il raggio della media focale. Quindi, per enormi quantità di sfocatura, vorrai ricominciare da capo con un quartiere di ampio raggio. Se si utilizza una media focale non ponderata, eseguire 5-6 passaggi sopra il DEM. Se si utilizzano pesi approssimativamente gaussiani, è necessario un solo passaggio: ma è necessario creare la matrice del peso.

Questo approccio ha in effetti la media aritmetica del DEM come valore limitante.


1
Se i tuoi dati hanno picchi, potresti provare un filtro mediano ( en.wikipedia.org/wiki/Median_filter ) prima di applicare una sfocatura più generale come suggerito da whuber.
MerseyViking

@Mersey Questo è un suggerimento eccellente. Non ho mai visto un DEM con valori anomali locali, ma poi non ho mai più dovuto elaborare un DEM grezzo (come risultati LIDAR non elaborati). Non puoi fare filtri mediani con FFT, ma hai solo (di solito) bisogno di un quartiere 3 x 3, quindi è comunque un'operazione veloce.
whuber

Grazie whuber. Devo ammettere che ho sempre usato solo dati LiDAR pre-elaborati, ma ci sono alcuni picchi significativi nei dati SRTM che trarrebbero beneficio da un filtro mediano. Tendono a essere larghi 2 o 3 campioni, quindi sarebbe necessario un filtro mediano più grande.
MerseyViking

@Mersey Stai ancora bene con un filtro mediano più grande di 5 x 5 o 7 x 7. Se stai contemplando (diciamo) un filtro 101 x 101, però, preparati ad aspettare! Suggerisci anche un punto importante che merita di essere elaborato: è una buona idea eseguire un'analisi esplorativa del DEM prima di fare qualsiasi cosa. Ciò includerebbe l'identificazione di picchi (valori anomali locali) e la caratterizzazione delle loro dimensioni ed estensioni. Volete essere sicuri che siano davvero artefatti (e non qualche vero fenomeno) prima di spazzarli via con un filtro!
whuber

1
+1 per FFT sui dati di elevazione. In realtà ho fatto quel lavoro in erba per i dati NED a 32 bit per rimuovere lo striping bidirezionale. Alla fine, questo è stato anche problematico perché ha reintrodotto l'effetto di terrazzamento che affligge molti altri DEM derivati ​​dal contorno.
Jay Guarneri,

43

Ho esplorato l' approccio signal.convolve di SciPy (basato su questo libro di cucina ) e sto riscuotendo un bel successo con il seguente frammento:

import numpy as np
from scipy.signal import fftconvolve

def gaussian_blur(in_array, size):
    # expand in_array to fit edge of kernel
    padded_array = np.pad(in_array, size, 'symmetric')
    # build kernel
    x, y = np.mgrid[-size:size + 1, -size:size + 1]
    g = np.exp(-(x**2 / float(size) + y**2 / float(size)))
    g = (g / g.sum()).astype(in_array.dtype)
    # do the Gaussian blur
    return fftconvolve(padded_array, g, mode='valid')

Lo uso in un'altra funzione che legge / scrive GeoTIFF float32 tramite GDAL (non è necessario ridimensionare a 0-255 byte per l'elaborazione delle immagini) e sto usando tentativi di dimensioni dei pixel (ad es. 2, 5, 20) e ha uscita davvero bella (visualizzata in ArcGIS con pixel 1: 1 e intervallo min / max costante):

DTM gaussiano

Nota: questa risposta è stata aggiornata per utilizzare una funzione di elaborazione signal.fft basata su FFT molto più veloce .


1
+1 Bella soluzione! Non lo so per certo, ma è una buona scommessa che signal.convolve utilizza gli FFT.
whuber

Stavo cercando un codice di sfocatura per uno strumento di cucitura automatica che sto scrivendo e ci siamo imbattuti in questo. Bel lavoro @MikeToews!
Ragi Yaser Burhum,

@RagiYaserBurhum Mi piacerebbe saperne di più sul tuo strumento. MikeToews Ottima risposta e frammento di codice molto apprezzato.
Jay Laura,

@JayLaura Niente di speciale, solo scrivendo uno strumento per mettere automaticamente in automatico alcune immagini che ho scattato con alcuni amici con un palloncino. Utilizzo delle classi Orfeo Toolbox orfeo-toolbox.org/SoftwareGuide/…
Ragi Yaser Burhum

2
@whuber dopo aver rivisto questa routine, non stava usando FFT, ma è ora ed è molto più veloce.
Mike T,

4

Questo potrebbe essere un commento all'ottima risposta di MikeT , se non fosse troppo lungo e troppo complesso. Ci ho giocato molto e ho realizzato un plugin QGIS chiamato FFT Convolution Filters (ancora in fase "sperimentale") basato sulla sua funzione. Oltre al livellamento, il plugin può anche affinare i bordi sottraendo il raster levigato da quello originale.

Ho aggiornato un po 'la funzione di Mike nel processo:

def __gaussian_blur1d(self, in_array, size):
        #check validity
        try:
            if 0 in in_array.shape:
                raise Exception("Null array can't be processed!")
        except TypeError:
            raise Exception("Null array can't be processed!")
        # expand in_array to fit edge of kernel
        padded_array = np.pad(in_array, size, 'symmetric').astype(float)
        # build kernel
        x, y = np.mgrid[-size:size + 1, -size:size + 1]
        g = np.exp(-(x**2 / float(size) + y**2 / float(size)))
        g = (g / g.sum()).astype(float)
        # do the Gaussian blur
        out_array = fftconvolve(padded_array, g, mode='valid')
        return out_array.astype(in_array.dtype)

I controlli di validità sono abbastanza evidenti, ma l'importante è lanciare e fluttuare. Prima di ciò, la funzione rendeva le matrici di numeri interi nere (solo zeri), a causa della divisione per la somma dei valori ( g / g.sum()).


3

In QGIS, ho ottenuto facilmente buoni risultati utilizzando il filtro immagine di Orfeo Toolbox . È abbastanza veloce e la modalità batch funziona bene. Sono disponibili diffusioni gaussiane, medie o anisotrope.

Si noti che si Radiusriferisce al numero di celle, non alla distanza.

Ecco un esempio usando Smoothing (gaussian) :

  • Crudo:

    Senza Filtro

  • filtrata:

    filtro


1

Bella soluzione per la sfocatura gaussiana e l'animazione cool. Per quanto riguarda lo strumento Filtro Esri sopra menzionato, questo è fondamentalmente solo lo strumento "Focal Statistics" Esri codificato in modo duraturo 3x3. Lo strumento Statistiche focali offre molte più opzioni sulla forma del filtro mobile, sulla dimensione e sulla statistica che si desidera eseguire. http://desktop.arcgis.com/en/arcmap/latest/tools/spatial-analyst-toolbox/focal-statistics.htm

Puoi anche creare un filtro "irregolare" in cui passi nel tuo file di testo con i pesi da utilizzare per ogni cella. Il file di testo ha tutte le righe desiderate nell'area del filtro, con valori delimitati da spazi bianchi per le colonne. Immagino che dovresti sempre usare un numero dispari di righe e colonne, quindi la tua cella di destinazione è nel mezzo.

Ho creato un foglio di calcolo Excel per giocare con pesi diversi che ho appena copiato / incollato in questo file. Dovresti ottenere gli stessi risultati di cui sopra se modifichi le formule.

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.