как наложить шейп-файл и растр?

18

У меня есть шейп-файл с полигонами. И у меня есть глобальный растровый файл. Я хочу наложить полигоны шейп-файла на растровую сетку и рассчитать среднее значение растра для каждого полигона.

Как я могу сделать это с помощью GDAL, записав результаты в шейп-файл?

andreash
источник
4
Является ли GDAL единственным инструментом, который вы хотели бы использовать?
Симбамангу
@ Симбамангу нет, в принципе все хорошо, и было бы здорово, если бы это было на Python
andreash

Ответы:

9

В R вы можете сделать

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

e - вектор со средними значениями растровых ячеек для каждого многоугольника.

Roberth
источник
Это R не Python, как задали в вопросе
GM
6

Следуя совету, который я получил в списке рассылки gdal-dev, я использовал StarSpan :

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

Результаты сохраняются в формате CSV. В то время этого уже было достаточно для меня, но должна быть возможность каким-то образом создать Shapefile из этой информации.

andreash
источник
StarSpan, похоже, перешел на GitHub. Получите это здесь .
Ричард
5

Следующий скрипт позволяет вам выполнить задачу с 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)
ustroetz
источник
4

Загрузите свой шейп-файл и свой растр в PostGIS 2.0 и выполните:

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» означает запись нулевого значения в полосу 1 целевого файла (work.tif). «-I» означает инвертированную растеризацию, поэтому мы записываем значения вне многоугольника, а не внутри него. Команда gdalinfo с параметром -stats сообщает о статистике группы. Я считаю, что это исключит значение nodata (которое мы пометили ранее с -a_nodata).

Фрэнк Вармердам
источник
2

Преобразуйте файл формы в растр с помощью gdal_rasterize и используйте код в http://www.spatial-ecology.net/dokuwiki/doku.php?id=wiki:geo_tools для вычисления зональной статистики для каждого многоугольника. Вы можете запустить http://km.fao.org/OFwiki/index.php/Oft-reclass, если хотите получить tif со своей статистикой растров. Наслаждайтесь кодом Ciao Giuseppe

Giuseppe
источник
У вас есть копия кода, на который вы ссылаетесь? К сожалению, ссылка на файл Python не работает.
Устроец
1

Это невозможно при использовании GDAL. Вы можете использовать другие бесплатные инструменты, например, saga gis:

saga_cmd shapes_grid "Grid Values to Shapes" -GRIDS=grid.sgrd -POLYGONS=in.shp -SHAPES=out.shp-NODATA -TYPE=1
johanvdw
источник
Я пошел с этим подходом, хотя имя функции на самом деле "Статистика сетки для полигонов".
банановая рыба
1

Вы также можете использовать rasterstats, это модуль Python, разработанный для этой цели:

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

введите описание изображения здесь

Затем вы можете получить доступ к атрибуту первой зоны, используя:

mean_of_zone1 = listofzones[0]['mean']
GM
источник
-2

Вы можете использовать инструмент для расчета статистики точек в Arc Arc, и этот инструмент можно скачать с http://ianbroad.com/arcgis-toolbox-calculate-point-statistics-polygon-arcpy/

Суреш Госвами
источник
2
«Инструмент« Рассчитать статистику точек »берет входной класс объектов« Полигон »и« Точка »и использует выбранное поле для нахождения минимума, максимума и среднего значения точек и добавляет результаты к объекту полигона». но этот вопрос о классе объектов Polygon и растре, поэтому он вряд ли подойдет.
PolyGeo