Обтравочный растр с векторным слоем с использованием GDAL

26

Я установил GDAL с помощью установщика Osgeo. Как программно обрезать растровый слой векторным слоем? Есть ли какой-нибудь GDAL API, который может помочь мне в этом? Я использую Python.

Vicky
источник

Ответы:

13

Я не уверен , о библиотеке GDAL апи, есть void* GDALWarpOptions::hCutlineв Options Деформации ссылки из API учебника Деформации , но никаких явных примеров. Вы уверены, что вам нужен программный ответ? Утилиты командной строки могут сделать это из коробки:

  1. создать шейп-файл, содержащий только интересующий нас полигон
  2. использовать ogrinfoдля определения степени отсечения шейп-файла
  3. использовать gdal_translateдля обрезки по форме экстентов
  4. использовать gdalwarpс -cutlineпараметром

Шаги 2 и 3 для оптимизации, вы можете обойтись только с gdalwarp -cutline ....

См. Обрезка растров с помощью GDAL с использованием полигонов из Linfinity для решения на основе linux, заключенных в один скрипт. Еще один пример вырезки можно увидеть в учебнике Майкла Кори, посвященном созданию холмов для Mapnik .

Мэтт Уилки
источник
Мэтт, вы, возможно, помните, что trac.osgeo.org/gdal/ticket/1599 выглядит так, как будто это делает вырезка
Майк Т
10

Джоэл Лоухед из GeospatialPython имеет полный пример Python в растре Clip с использованием shapefile , хорошо написанного учебника. Вам нужно будет установить библиотеку изображений Python (PIL), которая не включена в Osgeo4W (для этого вам может понадобиться добавить o4w python в реестр Windows, чтобы заставить программу установки работать).

Мэтт Уилки
источник
10

Кажется, эта тема всегда возвращается. Я сам не знал, что GDAL> 1.8 настолько продвинут, что уже дает вам честную обработку командной строки для выполнения этой задачи.

Комментарий от Mike Toews довольно полезен, но вы можете просто сделать, например:

gdalwarp -of GTiff -cutline DATA/area_of_interest.shp -cl area_of_interest  -crop_to_cutline DATA/PCE_in_gw.asc  data_masked7.tiff 

Вы можете обернуть эту команду внутри скрипта Python с помощью превосходного модуля подпроцесса .

Одна вещь, которая была для меня действительно проблематичной, заключается в том, что мне нужно было найти минимальное решение этой проблемы, то есть максимально простое и не требующее многих внешних зависимостей. Использование Python Imaging Library, как в учебном пособии Джоэла Лоухеда, очень удобно, но я нашел следующее решение: использование масок Numpy.
Я не знаю, лучше ли это, но это было то, что я знал назад, чем (3 года назад ...).
Первоначально я создал допустимую область данных внутри исходного растра (например, экстент выходного растра, где тот же), но мне понравилась идея сделать растр также меньшим (например, -crop_to_cutline), поэтому я принял world2Pixelот Джоэла Лоухеда. Вот мое собственное решение:

def RasterClipper():
    craster = MaskRaster()
    contraster2 = 'PCE_in_gw.aux'
    craster.reader("DATA/"+contraster2.replace('aux','asc'))
    xres, yres = craster.extent[1], craster.extent[1]
    craster.fillrasterpoints(xres, yres)
    craster.getareaofinterest("DATA/area_of_interest.shp")
    minX, maxX=craster.new_extent [0]-5,craster.new_extent[1]+5
    minY, maxY= craster.new_extent [2]-5,craster.new_extent[3]+5
    ulX, ulY=world2Pixel(craster.extent, minX, maxY)
    lrX, lrY=world2Pixel(craster.extent, maxX, minY)
    craster.getmask(craster.corners)
    craster.mask=np.logical_not(craster.mask)
    craster.mask.resize(craster.Yrange.size,craster.Xrange.size)
    # choose all data points inside the square boundaries of the AOI,
    # replace all other points with NULL
    craster.cdata= np.choose(np.flipud(craster.mask), (craster.data, -9999))
    # resise the data set to be the size of the squared polygon
    craster.ccdata=craster.cdata[ulY:lrY, ulX:lrX]
    craster.writer("ccdata2m.asc",craster.ccdata, (minX+xres*.5, maxY+yres*.5), 10,10,Flip=False)
    # in second step we rechoose all the data points which are inside the
    # bounding vertices of AOI
    # need to re-define our raster points
    craster.xllcorner, craster.yllcorner = minX, minY
    craster.xurcorner, craster.yurcorner = maxX, maxY
    craster.fillrasterpoints(10,10)
    craster.getmask(craster.boundingvertices) # just a wrapper around matplotlib.nxutils.points_in_poly
    craster.data=craster.ccdata
    craster.clip2(new_extent_polygon=craster.boundingvertices)
    craster.data = np.ma.MaskedArray(craster.data, mask=craster.mask)
    craster.data = np.ma.filled(craster.data, fill_value=-9999)
    # write the raster to disk
    craster.writer("ccdata2m_clipped.asc",craster.data, (minX+xres*.5, maxY+yres*.5), 10,10,Flip=False)

для полного описания class MaskRasterи его методов, смотрите github моего проекта .

Используя этот код, вам все равно нужно будет использовать GDAL. Однако в будущем планируется использовать чистый Python, где я могу, потому что предполагаемая аудитория моего программного обеспечения испытывает трудности с слишком большим количеством зависимостей (я использую Debian для разработки программного обеспечения, а клиенты используют Windows 7 ...).

Oz123
источник
Мне нравится пример командной строки, который вы привели, но можете ли вы объяснить, что делает аргумент -crop_to_cutline? Я не уверен, какова его цель, заданный подрезанный шейп-файл -cutline.
Хендра
1
опция -cutline обрезает растр к внутренней ограничительной рамке слоя многоугольника. Например, если он меньше в экстентах, выходной растр также будет меньше. Без этого выходной растр будет иметь тот же размер, что и оригинал, но с NULL во всех точках за пределами области, которая вас интересует.
Oz123