如何叠加shapefile和栅格?


17

我有一个带有多边形的shapefile。而且我有一个全局栅格文件。我想将shapefile的多边形覆盖到栅格网格上,并计算每个多边形的平均栅格值。

如何使用GDAL将结果写入shapefile?


4
GDAL是您唯一要使用的工具吗?
Simbamangu 2012年

@Simbamangu不,基本上任何事情都可以,如果使用Python
那就太好了

Answers:


9

在R中你可以做

library(raster)
library(rgdal)
r <- raster('raster_filename')
p <- readOGR('shp_path', 'shp_file')
e <- extract(r, p, fun=mean)

e是一个矢量,具有每个多边形的栅格像元值的平均值。


这不是问题所要求的R python
GM

6

遵循我在gdal-dev邮件列表中得到的建议,我使用了StarSpan

starspan --vector V --raster R1 R2 ... --stats mystats.csv avg mode

结果保存为CSV格式。那时,这对我来说已经足够了,但是应该可以从该信息中以某种方式伪造一个Shapefile。


StarSpan似乎已移至GitHub。在这里得到它。
理查德

4

在PostGIS 2.0中加载shapefile和栅格,然后执行以下操作:

SELECT (ST_SummaryStats(ST_Clip(rast, geom))).*
FROM rastertable, geomtable

4

我认为GDAL并不是最好的工具,但是您可以使用gdal_rasterize来“清除”多边形外的所有值。

就像是:

gdal_translate -a_nodata 0 original.tif work.tif
gdal_rasterize -burn 0 -b 1 -i work.tif yourpolygon.shp -l yourpolygon
gdalinfo -stats work.tif
rm work.tif

gdal_rasterize程序会修改文件,因此我们进行复制。我们还将某些特定值(在这种情况下为零)标记为nodata。“ -burn 0 -b 1”表示将零值刻录到目标文件(work.tif)的band 1中。“ -i”表示反转栅格化,因此我们在多边形外部而不是多边形内部刻录值。带-stats的gdalinfo命令报告频段统计信息。我相信它将排除nodata值(我们之前用-a_nodata标记了该值)。


4

以下脚本允许您使用GDAL执行任务:http : //pcjericks.github.io/py-gdalogr-cookbook/raster_layers.html#calculate-zonal-statistics

# Calculates statistics (mean) on values of a raster within the zones of an polygon shapefile

import gdal, ogr, osr, numpy

def zonal_stats(input_value_raster, input_zone_polygon):

    # Open data
    raster = gdal.Open(input_value_raster)
    driver = ogr.GetDriverByName('ESRI Shapefile')
    shp = driver.Open(input_zone_polygon)
    lyr = shp.GetLayer()

    # get raster georeference info
    transform = raster.GetGeoTransform()
    xOrigin = transform[0]
    yOrigin = transform[3]
    pixelWidth = transform[1]
    pixelHeight = transform[5]

    # reproject geometry to same projection as raster
    sourceSR = lyr.GetSpatialRef()
    targetSR = osr.SpatialReference()
    targetSR.ImportFromWkt(raster.GetProjectionRef())
    coordTrans = osr.CoordinateTransformation(sourceSR,targetSR)
    feat = lyr.GetNextFeature()
    geom = feat.GetGeometryRef()
    geom.Transform(coordTrans)

    # Get extent of geometry
    ring = geom.GetGeometryRef(0)
    numpoints = ring.GetPointCount()
    pointsX = []; pointsY = []
    for p in range(numpoints):
            lon, lat, z = ring.GetPoint(p)
            pointsX.append(lon)
            pointsY.append(lat)
    xmin = min(pointsX)
    xmax = max(pointsX)
    ymin = min(pointsY)
    ymax = max(pointsY)

    # Specify offset and rows and columns to read
    xoff = int((xmin - xOrigin)/pixelWidth)
    yoff = int((yOrigin - ymax)/pixelWidth)
    xcount = int((xmax - xmin)/pixelWidth)+1
    ycount = int((ymax - ymin)/pixelWidth)+1

    # create memory target raster
    target_ds = gdal.GetDriverByName('MEM').Create('', xcount, ycount, gdal.GDT_Byte)
    target_ds.SetGeoTransform((
        xmin, pixelWidth, 0,
        ymax, 0, pixelHeight,
    ))

    # create for target raster the same projection as for the value raster
    raster_srs = osr.SpatialReference()
    raster_srs.ImportFromWkt(raster.GetProjectionRef())
    target_ds.SetProjection(raster_srs.ExportToWkt())

    # rasterize zone polygon to raster
    gdal.RasterizeLayer(target_ds, [1], lyr, burn_values=[1])

    # read raster as arrays
    banddataraster = raster.GetRasterBand(1)
    dataraster = banddataraster.ReadAsArray(xoff, yoff, xcount, ycount).astype(numpy.float)

    bandmask = target_ds.GetRasterBand(1)
    datamask = bandmask.ReadAsArray(0, 0, xcount, ycount).astype(numpy.float)

    # mask zone of raster
    zoneraster = numpy.ma.masked_array(dataraster,  numpy.logical_not(datamask))

    # calculate mean of zonal raster
    return numpy.mean(zoneraster)


1

使用GDAL是不可能的。但是,您可以使用其他免费工具,例如saga gis:

saga_cmd shapes_grid "Grid Values to Shapes" -GRIDS=grid.sgrd -POLYGONS=in.shp -SHAPES=out.shp-NODATA -TYPE=1

我采用了这种方法,尽管函数名称实际上是“多边形的网格统计信息”。
香蕉鱼

1

您也可以使用 rasterstats thas是为此目的而设计的Python模块:

from rasterstats import zonal_stats
listofzones = zonal_stats("polygons.shp", "elevation.tif",
            stats="mean")

在此处输入图片说明

然后,您可以使用以下命令访问第一个区域的属性:

mean_of_zone1 = listofzones[0]['mean']

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.