Hiệu suất trong việc tính toán số liệu thống kê raster trong PostGIS


9

Tôi đang cố gắng tính toán thống kê raster (tối thiểu, tối đa, trung bình) cho mỗi đa giác trong một lớp vectơ bằng PostgreQuery / PostGIS.

Câu trả lời này của GIS.SE mô tả cách thực hiện điều này, bằng cách tính toán giao điểm giữa đa giác và raster và sau đó tính trung bình có trọng số: https://gis.stackexchange.com/a/19858/12420

Tôi đang sử dụng truy vấn sau ( demraster của tôi ở đâu, topo_area_su_regionlà vectơ của tôi và toidlà một ID duy nhất:

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;

Điều này hoạt động, nhưng nó quá chậm. Lớp vectơ của tôi có 2489k tính năng, với mỗi tính năng mất khoảng 90ms để xử lý - sẽ mất nhiều ngày để xử lý toàn bộ lớp. Tốc độ tính toán dường như không được cải thiện đáng kể nếu tôi chỉ tính toán tối thiểu và tối đa (tránh các cuộc gọi đến ST_Area).

Nếu tôi thực hiện một phép tính tương tự bằng Python (GDAL, NumPy và PIL), tôi có thể giảm đáng kể lượng thời gian cần thiết để xử lý dữ liệu, nếu thay vì vector hóa raster (sử dụng ST_Intersection) tôi sẽ quét vectơ. Xem mã tại đây: https://gist.github.com/snorfalorpagus/7320167

Tôi thực sự không cần một mức trung bình có trọng số - một cách tiếp cận "nếu nó chạm vào, nó là" đủ tốt - và tôi chắc chắn chắc chắn đây là điều đang làm mọi thứ chậm lại.

Câu hỏi : Có cách nào để khiến PostGIS hành xử như thế này không? tức là trả về các giá trị của tất cả các ô từ raster mà đa giác chạm vào, thay vì giao điểm chính xác.

Tôi rất mới với PostgreSQL / PostGIS, vì vậy có thể có điều gì đó khác mà tôi không làm đúng. Tôi đang chạy PostgreSQL 9.3.1 và PostGIS 2.1 trên Windows 7 (2.9GHz i7, RAM 8GB) và đã điều chỉnh cấu hình cơ sở dữ liệu như được đề xuất tại đây: http://postgis.net/workairs/postgis-intro/tuning.html

nhập mô tả hình ảnh ở đây


1
Tôi đã chỉnh sửa câu trả lời của mình. Tôi quên nói rằng giao điểm trong câu trả lời của tôi kém chính xác hơn.
Stefan

Câu trả lời:


11

Bạn nói đúng, sử dụng ST_Intersectionlàm chậm truy vấn của bạn đáng chú ý.

Thay vì sử dụng ST_Intersection, tốt hơn là cắt ( ST_Clip) raster của bạn với đa giác (các trường của bạn) và kết quả là đa giác ( ST_DumpAsPolygons). Vì vậy, mỗi ô raster sẽ được chuyển đổi thành một hình chữ nhật đa giác nhỏ với các giá trị riêng biệt.

Để nhận tối thiểu, tối đa hoặc trung bình từ các bãi chứa, bạn có thể sử dụng các câu lệnh tương tự.

Truy vấn này nên thực hiện thủ thuật:

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;

Trong câu lệnh ST_Clipbạn xác định raster, dải raster (= 1), đa giác và nếu crop nên là TRUE hoặc FALSE.

Bên cạnh đó bạn có thể sử dụng avg((gv).val)để tính giá trị trung bình.

BIÊN TẬP

Kết quả của cách tiếp cận của bạn là chính xác hơn, nhưng chậm hơn. Kết quả của sự kết hợp ST_ClipST_DumpAsPolygonsđang bỏ qua các ô raster đang giao nhau với kích thước nhỏ hơn 50% (hoặc 51%).

Hai ảnh chụp màn hình từ giao lộ CORINE Land Use cho thấy sự khác biệt. Hình ảnh đầu tiên với ST_Intersection, thứ hai với ST_ClipST_DumpAsPolygons.

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.