Como acessar com eficiência arquivos com GDAL a partir de um bucket S3 usando o VSIS3?

18

Portanto, a GDAL adicionou recentemente um novo recurso que permite a leitura aleatória dos arquivos de bucket do S3. Estou procurando cortar imagens GDAL de vários blocos de uma imagem sem ter que baixar o arquivo inteiro. Eu só vi documentação muito esparsa sobre como configurar e acessar um bucket S3 através do GDAL e estou um pouco confuso sobre como começar? Alguém teria a gentileza de fornecer um exemplo / tutorial extremamente curto sobre como definir o sistema de arquivos virtual para o GDAL para atingir esse objetivo? Pontos extras se sua solução permitir que ele seja script via Python!

Para esclarecer: Já o fizemos em Python. O problema com o Python é que você precisa fazer o download de toda a imagem para operá-la. A versão mais recente do GDAL suporta a montagem do balde S3, para que, se precisarmos recortar uma pequena porção da imagem, possamos operar diretamente nessa porção menor. Infelizmente, como o recurso foi lançado apenas na filial estável em janeiro, não encontrei nenhuma documentação sobre ele. Portanto, a solução deve usar o sistema VSI3 na versão mais recente do GDAL ou usar o sistema de maneira inteligente para impedir que o usuário precise baixar a imagem inteira em uma unidade EBS para operar nela.

Ou seja, a recompensa será concedida por responder que usa as APIs VSI encontradas nas versões mais recentes do GDAL, para que todo o arquivo não precise ser lido na memória ou no disco. Além disso, nós, os buckets que usamos nem sempre são públicos, portanto muitos dos truques HTTP publicados não funcionarão em muitas de nossas situações.

Skylion
fonte
Nenhuma experiência com S3 / buckets, mas esta postagem pode ser interessante: link . Utilizado de forma semelhante (?)
cm1
@ cm1 Obrigado, essa documentação tem sido a melhor ajuda até agora.
Skylion
Fico feliz em ouvir isso. Acho que essa é uma ótima pergunta que você fez e estou assistindo de perto. Espero que você / outras pessoas resolvam e publiquem uma boa solução aqui!
Cm1

Respostas:

18

Descobri que quando algo não está particularmente bem documentado no GDAL, é possível examinar os testes deles.

O /vsis3módulo de teste tem alguns exemplos simples, embora não tenha nenhum exemplo de leitura de partes de verdade.

Reunimos o código abaixo com base no módulo de teste, mas não consigo fazer o teste, pois o GDAL / vsis3 exige credenciais e não tenho uma conta da 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
fonte
2
Woot funciona como um encanto! Aqui está um exemplo de recorte da linha de comando: from_s3.tif
Skylion
Como são esses valores que você escondeu? Acho que KEY_ID é uma sequência curta de texto, como um nome de usuário. O que é ACCESS_KEY? Parece que é o que está em um arquivo pem, mas tem cerca de 1000 caracteres, portanto deve ser outra coisa.
Solx 07/02
Essas serão apenas seqüências de caracteres com números e letras, como um nome de usuário e senha. Você pode obter essas cordas, definindo papéis IAM no AWS
RutgerH
10

Como /vsis3/é implementado no GDAL, você também pode usar rasteriopara ler os conjuntos de dados do Windows S3. Isso requer que suas credenciais sejam configuradas para boto ou usando o manipulador de sessão rasterios da 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.

Veja também rasterios windowed-rw e documentos VSI .

Kersten
fonte
1

Tente usar um arquivo XML para armazenar as informações do WMS, mais detalhes estão na documentação do GDAL WMS .

Aqui está um exemplo de arquivo XML WMS para recuperar dados da API de elevação da 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>

Você pode então recortar em uma caixa delimitadora da seguinte maneira:

gdalwarp -of "GTiff" -te -13648825.0817 4552130.7825 -13627575.5878 4565507.2624 mapzen_wms.xml test.tif
Clhenrick
fonte
Embora essa seja uma resposta útil, já armazenamos os metadados em cache de maneira semelhante, mas queremos saber como usar a API do VSI para podermos cortar rapidamente pequenas porções de imagens grandes.
Skylion
Não tenho certeza se é porque o ponto de extremidade da API Mapzen é um WMS lado a lado, mas o código acima foi executado em menos de um minuto. Você tem certeza de que a API VSI será mais rápida?
clhenrick
Estamos trabalhando com MUITAS grandes rasters e grandes conjuntos de dados raster, o gargalo é definitivamente E / S. Além disso, os buckets que usamos são particulares e exigem credenciais, o que significa que o uso da API http S3 não funcionará no nosso caso. Não é que tenhamos que ler todas as imagens, é que sabemos que temos que cagar uma pequena porção de uma imagem muito grande.
Skylion
0

Não sei muito sobre os buckets S3, mas parece que é uma unidade de armazenamento em nuvem com autenticação usando serviços REST http. ou seja, poderia ser usado como um ponto de montagem comum, com um uri associado.

Se você procura cortar partes de imagens / varredura, o arquivo precisa estar em um formato apropriado.

Dê uma olhada na especificação do TMS http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification

(Talvez o netCDF também possa fazer o truque.)

O GDAL também lê e grava formatos TMS. Basicamente, é apenas uma estrutura de diretório padrão com alguns arquivos de metadados.

Agora, o truque é criar rapidamente o URL com os parâmetros de extensão geográfica por meio do driver TMS.

Dê uma olhada na documentação do driver OpenLayers TMS: http://dev.openlayers.org/docs/files/OpenLayers/Layer/TMS-js.html Para ver como ele lida com as solicitações com base na localização, zoom e extensão.

Claro que isso pode ser feito em Python. Você precisa primeiro criar o URI de "ponto de montagem" (ou caminho) apropriado com viscurl (de acordo com a documentação) e, depois de montado, vá para o bloco específico de acordo com a especificação TMS (que é uma extensão do caminho) .

Juan
fonte
Acabei de adicionar alguns esclarecimentos para diferenciá-lo do uso da interface S3 no Python.
Skylion