Leistung bei der Berechnung von Rasterstatistiken in PostGIS

9

Ich versuche, Raster-Statistiken (min, max, mean) für jedes Polygon in einer Vektorebene mit PostgreSQL / PostGIS zu berechnen.

In dieser GIS.SE-Antwort wird beschrieben, wie Sie dies tun, indem Sie den Schnittpunkt zwischen dem Polygon und dem Raster berechnen und anschließend einen gewichteten Durchschnitt berechnen: https://gis.stackexchange.com/a/19858/12420

Ich verwende die folgende Abfrage (wo demist mein Raster, topo_area_su_regionist mein Vektor und toidist eine eindeutige ID:

SELECT toid, Min((gv).val) As MinElevation, Max((gv).val) As MaxElevation, Sum(ST_Area((gv).geom) * (gv).val) / Sum(ST_Area((gv).geom)) as MeanElevation FROM (SELECT toid, ST_Intersection(rast, geom) AS gv FROM topo_area_su_region,dem WHERE ST_Intersects(rast, geom)) foo GROUP BY toid ORDER BY toid;

Das funktioniert, ist aber zu langsam. Meine Vektorebene verfügt über 2489.000 Features, deren Verarbeitung jeweils etwa 90 ms dauert. Die Verarbeitung der gesamten Ebene würde Tage dauern . Die Geschwindigkeit der Berechnung scheint sich nicht wesentlich zu verbessern, wenn ich nur die Min- und Max-Werte berechne (wodurch die Aufrufe von ST_Area vermieden werden).

Wenn ich eine ähnliche Berechnung mit Python (GDAL, NumPy und PIL) durchführe, kann ich den Zeitaufwand für die Verarbeitung der Daten erheblich reduzieren, wenn ich anstelle der Vektorisierung des Rasters (mit ST_Intersection) den Vektor rastern möchte. Siehe Code hier: https://gist.github.com/snorfalorpagus/7320167

Ich brauche keinen gewichteten Durchschnitt - ein Ansatz "Wenn es berührt, ist es in" ist gut genug - und ich bin mir ziemlich sicher, dass dies die Dinge verlangsamt.

Frage : Gibt es eine Möglichkeit, PostGIS dazu zu bringen, sich so zu verhalten? dh, um die Werte aller Zellen aus dem Raster zurückzugeben, die ein Polygon berührt, und nicht den genauen Schnittpunkt.

Ich bin sehr neu in PostgreSQL / PostGIS. Vielleicht gibt es noch etwas, das ich nicht richtig mache. Ich verwende PostgreSQL 9.3.1 und PostGIS 2.1 unter Windows 7 (2,9 GHz i7, 8 GB RAM) und habe die Datenbankkonfiguration wie hier vorgeschlagen angepasst: http://postgis.net/workshops/postgis-intro/tuning.html

Geben Sie hier die Bildbeschreibung ein

Snorfalorpagus
quelle
1
Ich habe meine Antwort bearbeitet. Ich habe vergessen zu sagen, dass der Schnittpunkt in meiner Antwort weniger genau ist.
Stefan

Antworten:

11

Sie haben Recht, ST_Intersectionwenn Sie Ihre Abfrage verlangsamen, macht sich dies bemerkbar.

Anstatt es zu verwenden ST_Intersection, ist es besser, ST_ClipIhr Raster mit den Polygonen (Ihren Feldern) zu beschneiden () und das Ergebnis als Polygone ( ST_DumpAsPolygons) auszugeben . So wird jede Rasterzelle in ein kleines Polygonrechteck mit unterschiedlichen Werten konvertiert.

Für den Empfang von min, max oder mean aus den Dumps können Sie dieselben Anweisungen verwenden.

Diese Abfrage sollte den Trick machen:

SELECT 
    toid,
    Min((gv).val) As MinElevation,
    Max((gv).val) As MaxElevation,
    Sum(ST_Area((gv).geom) * (gv).val) / Sum(ST_Area((gv).geom)) as MeanElevation
FROM (
    SELECT 
        toid,
        ST_DumpAsPolygons(ST_Clip(rast, 1, geom, true)) AS gv
    FROM topo_area_su_region,dem 
        WHERE ST_Intersects(rast, geom)) AS foo 
            GROUP BY toid 
            ORDER BY toid;

In der Anweisung ST_Clipdefinieren Sie das Raster, das Rasterband (= 1), das Polygon und ob der Zuschnitt WAHR oder FALSCH sein soll.

Außerdem können Sie damit avg((gv).val)den Mittelwert berechnen.

BEARBEITEN

Das Ergebnis Ihres Ansatzes ist das genauere, aber das langsamere. Die Ergebnisse der Kombination von ST_Clipund ST_DumpAsPolygonsignorieren die Rasterzellen, die sich mit weniger als 50% (oder 51%) ihrer Größe schneiden.

Diese beiden Screenshots von einer CORINE Land Use-Kreuzung zeigen den Unterschied. Erstes Bild mit ST_Intersection, zweites mit ST_Clipund ST_DumpAsPolygons.

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Stefan
quelle