ประสิทธิภาพในการคำนวณสถิติแรสเตอร์ใน PostGIS


9

ฉันพยายามคำนวณสถิติแรสเตอร์ (ต่ำสุด, สูงสุด, ค่าเฉลี่ย) สำหรับแต่ละรูปหลายเหลี่ยมในเลเยอร์เวกเตอร์โดยใช้ PostgreSQL / PostGIS

คำตอบ GIS.SE นี้อธิบายวิธีการทำเช่นนี้โดยการคำนวณจุดตัดระหว่างรูปหลายเหลี่ยมและแรสเตอร์แล้วคำนวณค่าเฉลี่ยถ่วงน้ำหนัก: https://gis.stackexchange.com/a/19858/12420

ฉันใช้ข้อความค้นหาต่อไปนี้ (ซึ่งdemเป็นแรสเตอร์topo_area_su_regionของฉันคือเวกเตอร์ของฉันและtoidเป็นรหัสเฉพาะ:

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;

ใช้งานได้ แต่ช้าเกินไป เลเยอร์เวกเตอร์ของฉันมีคุณสมบัติ 2489k โดยแต่ละขั้นตอนใช้เวลาประมาณ90msในการประมวลผล - ต้องใช้เวลาหลายวันในการประมวลผลเลเยอร์ทั้งหมด ดูเหมือนว่าความเร็วของการคำนวณจะไม่ได้รับการปรับปรุงอย่างมีนัยสำคัญหากฉันคำนวณเพียงค่าต่ำสุดและสูงสุด (ซึ่งจะหลีกเลี่ยงการเรียกไปยัง ST_Area)

ถ้าฉันทำการคำนวณที่คล้ายกันโดยใช้ Python (GDAL, NumPy และ PIL) ฉันสามารถลดระยะเวลาที่ใช้ในการประมวลผลข้อมูลได้อย่างมีนัยสำคัญหากแทนที่ vectorizing the raster (โดยใช้ ST_Intersection) ฉันจะทำให้ rasterize เวกเตอร์ ดูรหัสที่นี่: https://gist.github.com/snorfalorpagus/7320167

ฉันไม่ต้องการค่าเฉลี่ยถ่วงน้ำหนัก - "ถ้าสัมผัสก็อยู่ในแนวทาง" ดีพอ - และฉันก็แน่ใจว่านี่คือสิ่งที่ทำให้ช้าลง

คำถาม : มีวิธีใดบ้างที่จะให้ PostGIS ทำงานเช่นนี้ คือการส่งคืนค่าของเซลล์ทั้งหมดจากแรสเตอร์ที่รูปหลายเหลี่ยมสัมผัสแทนที่จะเป็นจุดตัดที่แน่นอน

ฉันยังใหม่กับ PostgreSQL / PostGIS ดังนั้นอาจมีบางอย่างที่ฉันทำไม่ถูก ฉันใช้ PostgreSQL 9.3.1 และ PostGIS 2.1 บน Windows 7 (2.9GHz i7, 8GB RAM) และได้ปรับแต่งการตั้งค่าฐานข้อมูลตามที่แนะนำไว้ที่นี่: http://postgis.net/workshops/postgis-intro/tuning.html

ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันแก้ไขคำตอบของฉันแล้ว ฉันลืมบอกว่าจุดตัดในคำตอบของฉันนั้นแม่นยำน้อยกว่า
Stefan

คำตอบ:


11

คุณพูดถูกการใช้ST_Intersectionข้อความค้นหาของคุณช้าลงอย่างเห็นได้ชัด

แทนที่จะใช้ST_Intersectionจะเป็นการดีกว่าที่จะคลิป ( ST_Clip) แรสเตอร์ของคุณด้วยรูปหลายเหลี่ยม (เขตข้อมูลของคุณ) และทิ้งผลลัพธ์เป็นรูปหลายเหลี่ยม ( ST_DumpAsPolygons) ดังนั้นเซลล์แรสเตอร์ทุกอันจะถูกแปลงเป็นรูปหลายเหลี่ยมเล็ก ๆ น้อย ๆ ที่มีค่าแตกต่างกัน

สำหรับการรับนาทีจำนวนสูงสุดหรือค่าเฉลี่ยจากการทิ้งคุณสามารถใช้คำสั่งเดียวกันได้

แบบสอบถามนี้ควรทำเคล็ดลับ:

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;

ในคำสั่งที่ST_Clipคุณกำหนดแรสเตอร์วงแรสเตอร์ (= 1) รูปหลายเหลี่ยมและถ้าการครอบตัดควรเป็น TRUE หรือ FALSE

นอกจากนี้คุณสามารถใช้avg((gv).val)ในการคำนวณค่าเฉลี่ย

แก้ไข

ผลลัพธ์ที่ได้จากวิธีการของคุณนั้นแม่นยำกว่า แต่ก็ช้ากว่า ผลลัพธ์จากการรวมกันของST_ClipและST_DumpAsPolygonsกำลังเพิกเฉยต่อเซลล์แรสเตอร์ที่ตัดกันด้วยขนาดน้อยกว่า 50% (หรือ 51%) ของขนาด

ภาพหน้าจอสองภาพนี้จากสี่แยกการใช้ที่ดิน CORINE แสดงความแตกต่าง ภาพแรกกับST_Intersectionหนึ่งสองกับและST_ClipST_DumpAsPolygons

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.