Intersezione di un raster con un poligono con PostGIS - errore artefatto


15

Sto usando PostGIS2.0 per fare alcune intersezioni raster / poligoni. Sto incontrando difficoltà nel capire quale operazione dovrei usare e quale sia il modo più rapido per farlo. Il mio problema è il seguente:

  • Ho un poligono e un raster
  • Voglio trovare tutti i pixel che rientrano nel poligono e ottenere la somma del valore del pixel
  • E (problema aggiornato): sto ottenendo valori enormi per alcuni pixel che non esistono nel raster originale quando eseguo la query

Ho difficoltà a capire se dovrei usare ST_Intersects()o ST_Intersection(). Inoltre non so quale sia l'approccio migliore per sommare i miei pixel. Ecco il primo approccio che ho provato (n. 1):

SELECT 
    r.rast 
FROM
    raster as r, 
    polygon as p
WHERE
    ST_Intersects(r.rast, p.geom)

Questo restituisce un elenco di rastvalori, che non sono sicuro di cosa fare. Ho provato a calcolare le statistiche di riepilogo usando ST_SummaryStats()ma non sono sicuro se questa è la somma ponderata di tutti i pixel che si trovano all'interno del poligono.

SELECT  
        (result).count,
        (result).sum    
FROM (  
         SELECT 
            ST_SummaryStats(r.rast) As result
         FROM
            raster As r, 
            polygon As p
         WHERE
            ST_Intersects(r.rast, p.geom)    
    ) As tmp

L'altro approccio che ho provato (n. 2) utilizza ST_Intersection():

 SELECT
        (gv).geom,         
        (gv).val
 FROM 
 (
    SELECT 
        ST_Intersection(r.rast, p.geom) AS gv
    FROM 
        raster as r, 
        polygon as p           
    WHERE 
        ST_Intersects(r.rast, p.geom)

      ) as foo;

Questo restituisce un elenco di geometrie che analizzerò ulteriormente, ma suppongo che questo sia meno efficiente.

Non sono chiaro su quale sia anche l'ordine di funzionamento più rapido. Dovrei sempre scegliere raster, polygono polygon, raster, o convertire il poligono in un raster in modo che sia raster, raster?

EDIT: ho aggiornato l'approccio n. 2 con alcuni dettagli dal R.K.link di.

Usando l'approccio n. 2, ho notato il seguente errore nei risultati, che è parte del motivo per cui non ho capito l'output. Ecco l'immagine del mio raster originale e uno schema del poligono che viene utilizzato per intersecarlo, sovrapposto in alto:

inserisci qui la descrizione dell'immagine

Ed ecco il risultato dell'incrocio con PostGIS:

inserisci qui la descrizione dell'immagine

Il problema con il risultato è che vengono restituiti valori di 21474836, che non si trovano nel raster originale. Non ho idea del perché questo accada. Ho il sospetto che sia correlato a piccoli numeri da qualche parte (dividendo per quasi 0), ma restituisce il risultato sbagliato.


Per quanto riguarda il punto due, vuoi ottenere la somma dei valori dei pixel che intersecano il poligono?
RK,

Sì, ho usato ST_SummaryStats()per il n. 1, ma non sono sicuro di come farlo per il n. 2.
djq

Inserito un collegamento a un riferimento. Spero che aiuti.
RK,

2
Il valore massimo della scala nella tua mappa è il massimo di un intero con segno a 32 bit. Non so cosa significhi nel tuo caso, ma potrebbe avere a che fare con i valori NA. L'intervallo nella query potrebbe avere valori null che non sono gestiti correttamente. en.wikipedia.org/wiki/2147483647#2147483647_in_computing
yellowcap

6
FWIW, 21474836 non è il valore massimo di un int con segno a 32 bit. Tuttavia, 2 ^ 31-1 = 2147483647 è il massimo e si noti che 21474836 = 2147483647/100 (divisione intera). Ciò suggerisce che vengono generati internamente alcuni NA (forse lungo le celle di confine), che sono rappresentati come 2 ^ 31-1, e quindi il codice "dimentica" che questi sono NA e (forse in un processo di ricampionamento?) Li divide per 100.
whuber

Risposte:


6

Ho trovato un tutorial sull'intersezione di poligoni vettoriali con un'ampia copertura raster usando PostGIS WKT Raster . Potrebbe avere le risposte che stai cercando.

Il tutorial ha utilizzato due set di dati, un file di forma di punto che è stato bufferizzato per produrre poligoni e una serie di 13 raster di elevazione SRTM. Ci sono stati molti passaggi nel mezzo ma la query utilizzata per intersecare il raster e il vettore sembrava così:

 CREATE TABLE caribou_srtm_inter AS
 SELECT id, 
        (gv).geom AS the_geom, 
        (gv).val
 FROM (SELECT id, 
              ST_Intersection(rast, the_geom) AS gv
       FROM srtm_tiled,
            cariboupoint_buffers_wgs
       WHERE ST_Intersects(rast, the_geom)
      ) foo;

I valori sono stati quindi riepilogati utilizzando quanto segue:

 CREATE TABLE result01 AS
 SELECT id, 
        sum(ST_Area(ST_Transform(the_geom, 32198)) * val) / 
        sum(ST_Area(ST_Transform(the_geom, 32198))) AS meanelev
 FROM caribou_srtm_inter
 GROUP BY id
 ORDER BY id;

In realtà non conosco abbastanza PostGIS per spiegarlo, ma sembra proprio quello che stavi cercando di realizzare. Il tutorial dovrebbe fare luce sui passaggi intermedi. In bocca al lupo :)


Grazie @RK ho letto questo tutorial. Penso che il mio calcolo sia più semplice, ma sto ancora cercando di capire questo passaggio di base!
djq

2

Per quanto riguarda il punto 2 della domanda originale, molte delle versioni di sviluppo di Postgis 2.0 hanno utilizzato una versione della libreria GDAL che ha trasmesso float in ints. Se il tuo raster contiene valori float e stavi utilizzando una versione di GDAL inferiore alla 1.9.0 o una versione del pre-rilascio di PostGIS 2.0 che non chiamava correttamente GDALFPolygonize (), potresti riscontrare questo errore. I biglietti nei localizzatori di bug PostGIS e GDAL sono stati archiviati e chiusi. Questo bug era attivo al momento della domanda originale.

In termini di prestazioni, scoprirai che l'utilizzo ST_Intersects(raster, geom)è molto più veloce dell'uso ST_Intersects(geom, raster). La prima versione rasterizza la geometria e crea un'intersezione spazio-raster. La seconda versione vettorializza la geometria ed esegue un'intersezione spazio-vettore, che può essere un processo molto più costoso.


0

Avevo anche strani problemi ST_SummaryStatscon ST_Clip. Interrogare i dati in modo diverso mi ha detto che il valore minimo del mio raster era 32, quindi massimo 300, ma ST_SummaryStatsstava restituendo -32700 per i valori dei pixel nel mio poligono di destinazione.

Ho finito per hackerare il problema in questo modo:

WITH first AS (
   SELECT id, (ST_Intersection(geom, rast)).val
   FROM raster_table
   INNER JOIN vector_table ON ST_Intersects(rast, geom)
)
SELECT id, COUNT(val), SUM(val), AVG(val), stddev(val), MIN(val), MAX(val)
FROM first
GROUP BY id
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.