Как эффективно получить доступ к файлам с помощью GDAL из корзины S3 с помощью VSIS3?

19

Итак, GDAL недавно добавил новую функцию, которая позволяет произвольно читать файлы S3 Bucket. Я хочу обрезать изображения GDAL из нескольких фрагментов изображения, не загружая весь файл. Я только видел очень скудную документацию о том, как настроить и получить доступ к корзине S3 через GDAL, и я немного запутался, как начать? Будет ли кто-то достаточно любезен, чтобы предоставить чрезвычайно короткий пример / учебник о том, как можно настроить виртуальную файловую систему для GDAL для достижения этой цели? Бонусные баллы, если ваше решение позволяет создавать сценарии через Python!

Чтобы уточнить: мы уже сделали это на Python. Проблема с Python заключается в том, что вам нужно загрузить весь образ, чтобы работать с ним. Новейшая версия GDAL имеет поддержку для монтажа корзины S3, так что если нам нужно обрезать небольшую часть изображения, мы можем работать непосредственно с этой меньшей частью. Увы, поскольку эта функция была выпущена только в стабильной ветке в январе, я не нашел никакой документации по ней. Таким образом, решение должно использовать систему VSI3 в новейшей версии GDAL или иным образом разумно использовать систему, чтобы пользователю не требовалось загружать весь образ на диск EBS для работы с ним.

То есть награда будет присуждена за ответ, использующий API-интерфейсы VSI, обнаруженные в новейших версиях GDAL, так что весь файл не нужно будет читать в память или на диск. Кроме того, мы, используемые нами блоки, не всегда общедоступны, поэтому многие публикуемые трюки HTTP не будут работать во многих наших ситуациях.

Skylion
источник
Может быть интересен: github.com/mapbox/rasterio/issues/511 и gist.github.com/perrygeo/9239b9ab64731cacbb35
Чед Купер
Нет опыта работы с S3 / buckets, но этот пост может представлять интерес: ссылка . Используется аналогично (?)
см1
@ cm1 Спасибо, эта документация до сих пор была лучшей помощью.
Skylion
Рад это слышать. Я думаю, что это отличный вопрос, который вы задали, и я внимательно слежу. Надеюсь, что вы / другие решите и опубликуете хорошее решение здесь!
cm1

Ответы:

18

Я обнаружил, что когда что-то не очень хорошо задокументировано в GDAL, просмотр их тестов может быть полезным.

У /vsis3тестового модуля есть несколько простых примеров, хотя у него нет примеров реального чтения фрагментов.

Я собрал код ниже, основанный на тестовом модуле, но я не могу протестировать, поскольку GDAL / vsis3 требует учетные данные, и у меня нет учетной записи AWS.

"""This should read from the Sentinal-2 public dataset
   More info - http://sentinel-pds.s3-website.eu-central-1.amazonaws.com"""

from osgeo import gdal
import numpy as np

# These only need to be set if they're not already in the environment,
# ~/.aws/config, or you're running on an EC2 instance with an IAM role.
gdal.SetConfigOption('AWS_REGION', 'eu-central-1')
gdal.SetConfigOption('AWS_SECRET_ACCESS_KEY', 'MY_AWS_SECRET_ACCESS_KEY')
gdal.SetConfigOption('AWS_ACCESS_KEY_ID', 'MY_AWS_ACCESS_KEY_ID')
gdal.SetConfigOption('AWS_SESSION_TOKEN', 'MY_AWS_SESSION_TOKEN')

# 'sentinel-pds' is the S3 bucket name
path = '/vsis3/sentinel-pds/tiles/10/S/DG/2015/12/7/0/B01.jp2'
ds = gdal.Open(path)

band = ds.GetRasterBand(1)

xoff, yoff, xcount, ycount = (0, 0, 10, 10)
np_array = band.ReadAsArray(xoff, yoff, xcount, ycount)
user2856
источник
2
Woot работает как шарм! Вот пример обрезки из командной строки: bdw: gdal_translate --config AWS_REGION "some_region" --config AWS_ACCESS_KEY_ID "KEY_ID" --config AWS_SECRET_ACCESS_KEY "ACCESS_KEY" \ -srcwin 000 000 10003e_set \ from_s3.tif
Skylion
Как выглядят те ценности, которые вы спрятали? Я думаю, что KEY_ID является короткой текстовой строкой, как имя пользователя. Что такое ACCESS_KEY? Кажется, что это то, что находится в файле pem, но это около 1000 символов, так что это должно быть что-то еще.
Solx
Это будут просто строки с цифрами и буквами, вроде имени пользователя и пароля. Вы можете получить эти строки, установив роли IAM в AWS
RutgerH
10

Так /vsis3/как реализован в GDAL, вы также можете использовать rasterioдля чтения Windows наборов данных S3. Это требует либо учетные данные , которые будут созданы для Бота или с помощью rasterios AWS обработчика сеанса .

import rasterio

with rasterio.open('s3://landsat-pds/L8/139/045/LC81390452014295LGN00/LC81390452014295LGN00_B1.TIF') as ds:
    window = ds.read(window=((0, 100), (0, 100)))  # read a 100 by 100 window in the upper left corner.

Смотрите также растровые документы windowed -rw и VSI .

Керстен
источник
1

Попробуйте использовать файл XML для хранения информации WMS, более подробную информацию можно найти в документации по GDAL WMS .

Вот пример XML-файла WMS для извлечения данных из Elevation API Mapzen:

<GDAL_WMS>
  <Service name="TMS">
    <ServerUrl>https://s3.amazonaws.com/elevation-tiles-prod/geotiff/${z}/${x}/${y}.tif</ServerUrl>
  </Service>
  <DataWindow>
    <UpperLeftX>-20037508.34</UpperLeftX>
    <UpperLeftY>20037508.34</UpperLeftY>
    <LowerRightX>20037508.34</LowerRightX>
    <LowerRightY>-20037508.34</LowerRightY>
    <TileLevel>14</TileLevel>
    <TileCountX>1</TileCountX>
    <TileCountY>1</TileCountY>
    <YOrigin>top</YOrigin>
  </DataWindow>
  <Projection>EPSG:3857</Projection>
  <BlockSizeX>512</BlockSizeX>
  <BlockSizeY>512</BlockSizeY>
  <BandsCount>1</BandsCount>
  <DataType>Int16</DataType>
  <ZeroBlockHttpCodes>403,404</ZeroBlockHttpCodes>
  <DataValues>
    <NoData>-32768</NoData>
  </DataValues>
  <Cache/>
</GDAL_WMS>

Затем вы можете закрепить ограничивающую рамку следующим образом:

gdalwarp -of "GTiff" -te -13648825.0817 4552130.7825 -13627575.5878 4565507.2624 mapzen_wms.xml test.tif
clhenrick
источник
Хотя это полезный ответ, мы уже кэшируем метаданные подобным образом, но мы хотим знать, как использовать VSI API, чтобы мы могли быстро обрезать небольшие части больших изображений.
Skylion
Я не уверен, что это потому, что конечная точка API Mapzen является плиточной WMS, но приведенный выше код запустился для меня менее чем за минуту. Вы уверены, что API VSI будет работать быстрее?
Клэнрик
Мы работаем с ОЧЕНЬ большими растрами и большими наборами растровых данных, узким местом, безусловно, является IO. Кроме того, используемые нами хранилища являются частными и требуют учетных данных, что означает, что использование S3 http API не будет работать в нашем случае. Дело не в том, что мы должны читать каждое изображение, а в том, что мы знаем, что нужно обосрать небольшую часть очень большого изображения.
Skylion
0

Я не очень разбираюсь в сегментах S3, но, похоже, это облачный накопитель с аутентификацией с использованием служб http REST. т.е. может быть использован в качестве обычной точки крепления, с соответствующей URI.

Если вы ищете обрезку частей изображения / растра, тогда файл должен быть в соответствующем формате.

Посмотрите на спецификацию TMS http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification

(Возможно, netCDF также может помочь.)

GDAL также читает и записывает форматы TMS. По сути, это только стандартная структура каталогов с некоторыми файлами метаданных.

Теперь хитрость заключается в создании на лету URL-адреса с параметрами географического экстента через драйвер TMS.

Взгляните на документацию драйвера OpenLayers TMS: http://dev.openlayers.org/docs/files/OpenLayers/Layer/TMS-js.html Чтобы узнать, как он обрабатывает запросы на основе местоположения, масштаба и экстентов.

Конечно, это можно сделать на Python. Сначала необходимо создать соответствующий URI «точки монтирования» (или пути) с помощью viscurl (согласно документации), а затем, после монтирования, перейти к определенной плитке в соответствии со спецификацией TMS (которая является расширением пути). ,

Juan
источник
Я просто добавил некоторые пояснения, чтобы отличить его от простого использования интерфейса S3 в Python.
Skylion