簡體   English   中英

從坐標參考系統中的多邊形邊界獲取柵格中的像素坐標

[英]Get pixel coordinates in raster from polygon boundary in coordinate reference system

我有一些相對較大的 GeoTiff 文件(10980 x 10980 像素),它們都對應於相同的地理區域(並且具有相同的坐標參考系統),並且我有大量的多邊形(100,000+)對應於地塊,我想從每個圖像文件中提取與每個多邊形對應的像素。 目前,我這樣做的方式是使用勻稱的多邊形和 rasterio.mask.mask 函數,如下所示:

for filename in image_files:
    with rasterio.open(filename) as src:
        for shape in shapes:
            data, _ = rasterio.mask.mask(src, [shape], crop=True)

這在經驗上相當緩慢。 如果我預先計算了掩碼索引,那么我只需要讀取每個圖像的整個數據一次,然后使用預先計算的索引來提取每個多邊形的相關像素(我不需要它們在正確的 2-維配置,我只需要值),這非常快。 但是不知道有沒有快速獲取這些像素索引的方法。 我知道我可以使用 rasterio 的raster_geometry_mask函數來獲取整個圖像大小的掩碼,然后使用 numpy 來獲取多邊形內元素的索引,但是這樣就不必要地為每個多邊形構建一個 10980 x 10980 的數組制作面具,這是非常非常緩慢的。

我最終做的是,當我打開第一個圖像時,然后對於每個多邊形,

  • 使用圖像變換將多邊形轉換為像素坐標,並在整數像素坐標中找到包含多邊形的矩形邊界框。
  • 要確定邊界框中的哪些像素實際上在多邊形中,請為每個像素構建勻稱的多邊形並使用.intersects()方法(如果您只想包含完全位於多邊形內部的像素,則可以使用.contains() )。 (我不確定這是否會很慢,但事實證明不會。)
  • 保存每個多邊形中所有像素的坐標對列表。

然后對於您打開的每個新圖像,您只需讀取整個圖像數據並索引每個多邊形的部分,因為您已經有了像素索引。

代碼大致如下所示:

import math
import numpy
import pyproj
import rasterio.mask
from shapely.geometry import Polygon

shape_pixels = None
for filename in image_files:
    with rasterio.open(filename) as src:
        if shape_pixels is None:
            projector = pyproj.Proj(src.crs)
            pixelcoord_shapes = [
                Polygon(zip(*(~src.transform * numpy.array(projector(*zip(*shape.boundary.coords))))))
                for shape in shapes
            ]

            pixels_per_shape = []
            for shape in shapes:
                xmin = max(0, math.floor(shape.bounds[0]))
                ymin = max(0, math.floor(shape.bounds[1]))
                xmax = math.ceil(shape.bounds[2])
                ymax = math.ceil(shape.bounds[3])
                pixel_squares = {}
                for j in range(xmin, xmax+1):
                    for i in range(ymin, ymax+1):
                        pixel_squares[(i, j)] = Polygon.from_bounds(j, i, j+1, i+1)
                pixels_per_shape.append([
                    coords for (coords, pixel) in pixel_squares.items()
                    if shape.intersects(pixel)
                ])

        whole_data = src.read()

        for pixels in pixels_per_shape:
            ivals, jvals = zip(*pixels)
            shape_data = whole_data[0, ivals, jvals]
            ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM