Rasterize một shapefile với Geopandas hoặc fiona - python


10

Tôi cần rasterize một shapefile thực sự đơn giản một chút như thế này http://tinyurl.com/odfbanu . Đây chỉ là một quận coutain shapefile ở Mỹ. Tôi đã thấy câu trả lời trước đây: GDAL RasterizeLayer không ghi tất cả đa giác cho Raster? nhưng tôi đã tự hỏi nếu có một cách để làm điều đó bằng cách sử dụng Geopandas hoặc fiona và có thể rasterio cho phần viết tiff.

Vì vậy, mục tiêu của tôi là rasterize nó và gán một giá trị cho mọi đa giác chia sẻ một giá trị comon, LSAD trong ví dụ.

Vì vậy, tôi đã viết phần đầu của mã được lấy cảm hứng từ shongololo trong chuỗi: Hòa tan đa giác dựa trên các thuộc tính với Python (shapely, fiona)? .

from geopandas import GeoDataFrame

name_in = 'cb_2013_us_county_20m.shp'

#Open the file with geopandas
counties = GeoDataFrame.from_file(name_in)

#Add a column to the Geodataframe containing the new value
for i in range (len(counties)):
    LSAD = counties.at[i,'LSAD']
    if LSAD == 00 :
        counties['LSAD_NUM'] == 'A'
    elif LSAD == 03 :
        counties['LSAD_NUM'] == 'B'
    elif LSAD == 04 :
        counties['LSAD_NUM'] == 'C'
    elif LSAD == 05 :
        counties['LSAD_NUM'] == 'D'
    elif LSAD == 06 :
        counties['LSAD_NUM'] == 'E'
    elif LSAD == 13 :
        counties['LSAD_NUM'] == 'F'
    elif LSAD == 15 :
        counties['LSAD_NUM'] == 'G'  
    elif LSAD == 25 :
        counties['LSAD_NUM'] == 'I'          
    else :
        counties['LSAD_NUM'] == 'NA'

Công cụ thực sự dễ dàng vì vậy bây giờ tôi tự hỏi làm thế nào tôi thực sự có thể viết những hình dạng đó cho một tiff. Tôi bắt đầu làm việc với Geopandas vì tôi tin rằng đó là lựa chọn tốt nhất nhưng nếu bạn có gợi ý về fiona thì tôi cũng đồng ý.

Tôi tìm thấy một đoạn mã từ rasterio mà dường như có thể lấy một hình dạng cân đối và ghi nó vào một raster mới http://tinyurl.com/op49uek

# I guess that my goal should be to load my list of geometries under geometry to be able to pass it to rasterio later on
geometry = {'type':'Polygon','coordinates':[[(2,2),(2,4.25),(4.25,4.25),(4.25,2),(2,2)]]}

with rasterio.drivers():
    result = rasterize([geometry], out_shape=(rows, cols))
    with rasterio.open(
            "test.tif",
            'w',
            driver='GTiff',
            width=cols,
            height=rows,
            count=1,
            dtype=numpy.uint8,
            nodata=0,
            transform=IDENTITY,
            crs={'init': "EPSG:4326"}) as out:
                 out.write_band(1, result.astype(numpy.uint8))

Câu trả lời là về GDALrasterize, tôi chính xác hỏi liệu ai đó có ý tưởng về việc làm điều tương tự bằng cách sử dụng Geopandas và rasterio. Không trùng lặp
User18981898198119

Tìm thấy một đoạn Mã có thể giúp ích, đăng bài đã được chỉnh sửa
User18981898198119

Câu trả lời:


19

Bạn đang đi đúng hướng và geopandas GeoDataFrame là một lựa chọn tốt cho việc rasterization trên Fiona. Fiona là một bộ công cụ tuyệt vời, nhưng tôi nghĩ rằng DataFrame phù hợp hơn với shapefiles và hình học so với từ điển lồng nhau.

import geopandas as gpd
import rasterio
from rasterio import features

Thiết lập tên tệp của bạn

shp_fn = 'cb_2013_us_county_20m.shp'
rst_fn = 'template_raster.tif'
out_fn = './rasterized.tif'

Mở tệp bằng GeoPANDAS read_file

counties = gpd.read_file(shp_fn)

Thêm cột mới (như trong mã trên của bạn)

for i in range (len(counties)):
    LSAD = counties.at[i,'LSAD']
    if LSAD == 00 :
        counties['LSAD_NUM'] == 'A'
    elif LSAD == 03 :
        counties['LSAD_NUM'] == 'B'
    elif LSAD == 04 :
        counties['LSAD_NUM'] == 'C'
    elif LSAD == 05 :
        counties['LSAD_NUM'] == 'D'
    elif LSAD == 06 :
        counties['LSAD_NUM'] == 'E'
    elif LSAD == 13 :
        counties['LSAD_NUM'] == 'F'
    elif LSAD == 15 :
        counties['LSAD_NUM'] == 'G'  
    elif LSAD == 25 :
        counties['LSAD_NUM'] == 'I'          
    else :
        counties['LSAD_NUM'] == 'NA'

Mở tệp raster bạn muốn sử dụng làm mẫu để ghi tính năng sử dụng rasterio

rst = rasterio.open(rst_fn)

sao chép và cập nhật siêu dữ liệu từ raster đầu vào cho đầu ra

meta = rst.meta.copy()
meta.update(compress='lzw')

Bây giờ ghi các tính năng vào raster và viết nó ra

with rasterio.open(out_fn, 'w+', **meta) as out:
    out_arr = out.read(1)

    # this is where we create a generator of geom, value pairs to use in rasterizing
    shapes = ((geom,value) for geom, value in zip(counties.geometry, counties.LSAD_NUM))

    burned = features.rasterize(shapes=shapes, fill=0, out=out_arr, transform=out.transform)
    out.write_band(1, burned)

Ý tưởng tổng thể là tạo ra một bộ lặp có chứa các bộ dữ liệu (hình học, giá trị), trong đó hình học là hình dạng hình học và giá trị là những gì bạn muốn ghi vào raster tại vị trí của hình học đó. Cả Fiona và GeoPANDAS đều sử dụng hình dạng cân đối để bạn gặp may mắn ở đó. Trong ví dụ này, một trình tạo được sử dụng để lặp qua các cặp (hình học, giá trị) được trích xuất từ ​​GeoDataFrame và được nối với nhau bằng zip ().

Hãy chắc chắn rằng bạn mở out_fntệp ở w+chế độ, bởi vì nó sẽ phải được sử dụng để đọc và viết.


1

geocube là một công cụ mới được thiết kế đặc biệt để rasterizing dữ liệu geopandas bao bọc rasterio. Nó đơn giản hóa quá trình và loại bỏ sự cần thiết của một raster mẫu.

https://github.com/corteva/geocube

Trong bối cảnh của ví dụ trên:

from geocube.api.core import make_geocube
import geopandas

counties = geopandas.read_file("zip://cb_2013_us_county_20m.zip/cb_2013_us_county_20m.shp")

Chữ cái có thể được đặt trên khung dữ liệu như vậy:

counties["LSAD_LETTER"] = 'NA'
lsad_letter = counties.LSAD_LETTER.copy()
lsad_letter[counties.LSAD=='00'] = 'A'
lsad_letter[counties.LSAD=='03'] = 'B'
lsad_letter[counties.LSAD=='04'] = 'C'
lsad_letter[counties.LSAD=='05'] = 'D'
lsad_letter[counties.LSAD=='06'] = 'E'
lsad_letter[counties.LSAD=='13'] = 'F'
lsad_letter[counties.LSAD=='15'] = 'G'
lsad_letter[counties.LSAD=='25'] = 'I'
counties["LSAD_LETTER"] = lsad_letter

Tuy nhiên, chỉ các giá trị số có thể được rasterized. Dưới đây là một ví dụ phân loại: https://corteva.github.io/geocube/urdy/examples/c sortical.html

Vì vậy, thay vì sử dụng số đó, hãy sử dụng các số ở định dạng chuỗi và chuyển đổi sang số nguyên:

counties["LSAD_NUM"] = counties.LSAD.astype(int)

Sau đó, rasterize dữ liệu:

cube = make_geocube(
    counties,
    measurements=["LSAD_NUM"],
    resolution=(1, -1),
)

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

Cuối cùng, xuất nó sang raster:

cube.LSAD_NUM.rio.to_raster("lsad_num.tif")
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.