PostGIS'te raster istatistiklerinin hesaplanmasında performans


9

PostgreSQL / PostGIS kullanarak bir vektör katmanındaki her çokgen için raster istatistikleri (min, max, ortalama) hesaplamaya çalışıyorum.

Bu GIS.SE cevabı, çokgen ve raster arasındaki kesişmeyi hesaplayıp ardından ağırlıklı bir ortalama hesaplayarak bunun nasıl yapılacağını açıklar: https://gis.stackexchange.com/a/19858/12420

Aşağıdaki sorguyu kullanıyorum ( demrasterim nerede , topo_area_su_regionvektörüm ve toidbenzersiz bir kimlik:

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;

Bu işe yarıyor, ama çok yavaş. Vektör katmanım 2489k özelliklere sahip, her birinin işlenmesi yaklaşık 90 ms sürüyor - tüm katmanın işlenmesi günler sürüyor . Hesaplamanın hızı, yalnızca min ve max'ı hesaplarsam (ST_Area çağrılarını önler) önemli ölçüde iyileşmiş gibi görünmüyor.

Python (GDAL, NumPy ve PIL) kullanarak benzer bir hesaplama yaparsam, raster vektörlemek yerine (ST_Intersection kullanarak) vektörü rasterleştiriyorum, verileri işlemek için gereken süreyi önemli ölçüde azaltabilirim. Kodu buradan görebilirsiniz: https://gist.github.com/snorfalorpagus/7320167

Gerçekten ağırlıklı bir ortama ihtiyacım yok - eğer bir "dokunursa, o" yaklaşımı yeterince iyidir - ve işlerin yavaşlatan şey olduğundan eminim.

Soru : PostGIS'in böyle davranmasını sağlamanın bir yolu var mı? yani, bir çokgenin tam kavşaktan ziyade temas ettiği rasterdeki tüm hücrelerin değerlerini döndürmek.

PostgreSQL / PostGIS için çok yeniyim, bu yüzden belki de doğru yapmadığım başka bir şey var. Windows 7'de (2.9 GHz i7, 8 GB RAM) PostgreSQL 9.3.1 ve PostGIS 2.1 kullanıyorum ve burada önerilen veritabanı yapılandırmasını değiştirdim: http://postgis.net/workshops/postgis-intro/tuning.html

resim açıklamasını buraya girin


1
Cevabımı düzenledim. Cevabımdaki kesişimin daha az doğru olduğunu söylemeyi unuttum.
Stefan

Yanıtlar:


11

Doğru, ST_Intersectionsorgunuzu belirgin şekilde yavaşlatır.

Kullanmak yerine , rasterinizi çokgenlerle (alanlarınız) ST_Intersectionkırpmak ( ST_Clip) ve sonucu çokgenler ( ST_DumpAsPolygons) olarak dökmek daha iyidir . Böylece her tarama hücresi farklı değerlere sahip küçük bir çokgen dikdörtgene dönüştürülecektir.

Dökümlerden min, maks veya ortalama almak için aynı ifadeleri kullanabilirsiniz.

Bu sorgu hile yapmalıdır:

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;

Açıklamada ST_Clipsen Resim, resim bandı (= 1), çokgen tanımlamak ve eğer ekin DOĞRU veya YANLIŞ olmalıdır.

Ayrıca avg((gv).val)ortalama değeri hesaplamak için de kullanabilirsiniz .

DÜZENLE

Yaklaşımınızın sonucu daha kesin, ancak daha yavaş olanıdır. Kombinasyonunun sonuçları ST_Clipve ST_DumpAsPolygonsbunların boyutunun en az% 50 (veya% 51) ile kesişen raster hücreler göz ardı edilir.

CORINE Arazi Kullanımı kavşağından alınan bu iki ekran görüntüsü farkı göstermektedir. İlk resim ST_Intersection, ikincisi ST_Clipve ST_DumpAsPolygons.

resim açıklamasını buraya girin

resim açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.