Comment accéder efficacement aux fichiers avec GDAL à partir d'un compartiment S3 en utilisant VSIS3?

19

Ainsi, GDAL a récemment ajouté une nouvelle fonctionnalité qui permet la lecture aléatoire des fichiers de compartiment S3. Je cherche à recadrer des images GDAL à partir de plusieurs tuiles d'une image sans avoir à télécharger le fichier entier. Je n'ai vu que très peu de documentation sur la façon de configurer et d'accéder à un compartiment S3 via GDAL et je suis un peu confus sur la façon de commencer? Est-ce que quelqu'un aurait la gentillesse de fournir un exemple / tutoriel extrêmement court sur la façon dont on procéderait pour configurer le système de fichiers virtuel pour GDAL afin d'atteindre cet objectif? Points bonus si votre solution permet de l'écrire via Python!

Pour clarifier: nous l'avons déjà fait en Python. Le problème avec Python est que vous devez télécharger l'image entière pour l'utiliser avec. La dernière version de GDAL prend en charge le montage du seau S3 de sorte que si nous devons dire un recadrage une petite partie de l'image, nous pouvons opérer directement sur cette plus petite partie. Hélas, comme la fonctionnalité n'est sortie que sur la branche stable en janvier, je n'ai trouvé aucune documentation à ce sujet. Ainsi, la solution doit utiliser le système VSI3 dans la dernière version de GDAL ou autrement utiliser intelligemment le système pour empêcher l'utilisateur d'avoir à télécharger l'image entière sur un lecteur EBS pour l'utiliser.

C'est-à-dire que la prime sera attribuée à la réponse qui utilise les API VSI présentes dans les dernières versions de GDAL afin que le fichier entier n'ait pas besoin d'être lu en mémoire ou sur disque. De plus, nous, les compartiments que nous utilisons, ne sommes pas toujours publics, donc bon nombre des astuces HTTP publiées ne fonctionneront pas dans bon nombre de nos situations.

Skylion
la source
Aucune expérience avec S3 / buckets, mais ce post peut être intéressant: lien . Utilisé de la même manière (?)
cm1
@ cm1 Merci, cette documentation a été la meilleure aide jusqu'à présent.
Skylion
Heureux de l'entendre. Je pense que c'est une excellente question que vous avez posée et que je regarde de près. J'espère que vous / les autres résolvez et postez une bonne solution ici!
cm1

Réponses:

18

J'ai découvert que lorsque quelque chose n'est pas particulièrement bien documenté dans GDAL, il peut être utile de parcourir leurs tests.

Le /vsis3module de test contient quelques exemples simples, bien qu'il ne contienne aucun exemple de lecture de morceaux.

J'ai bricolé le code ci-dessous basé sur le module de test, mais je ne peux pas tester car GDAL / vsis3 nécessite des informations d'identification et je n'ai pas de compte 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
la source
2
Woot fonctionne comme un charme! Voici un exemple de recadrage provenant de la ligne de commande btw: gdal_translate --config AWS_REGION "some_region" --config AWS_ACCESS_KEY_ID "KEY_ID" --config AWS_SECRET_ACCESS_KEY "ACCESS_KEY" \ -srcwin 000 000 1000 1000 \ "/vsis3/bc from_s3.tif
Skylion
À quoi ressemblent ces valeurs que vous avez cachées? Je pense que KEY_ID est une courte chaîne de texte, comme un nom d'utilisateur. Qu'est-ce que ACCESS_KEY? Il semble que ce soit ce qui se trouve dans un fichier pem mais c'est environ 1000 caractères, donc ça doit être autre chose.
Solx
Ce ne seront que des chaînes avec des chiffres et des lettres, un peu comme un nom d'utilisateur et un mot de passe. Vous pouvez obtenir ces chaînes en définissant des rôles IAM dans AWS
RutgerH
10

Depuis /vsis3/est implémenté dans GDAL, vous pouvez également utiliser rasteriopour lire les ensembles de données Windows de S3. Cela nécessite la configuration de vos informations d'identification pour boto ou l'utilisation du gestionnaire de session 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.

Voir aussi rasterios windowed -rw et VSI docs.

Kersten
la source
1

Essayez d'utiliser un fichier XML pour stocker les informations WMS dans, plus de détails sont dans la documentation GDAL WMS .

Voici un exemple de fichier XML WMS pour récupérer des données de l'API élévation de 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>

Vous pouvez ensuite découper dans un cadre de sélection comme suit:

gdalwarp -of "GTiff" -te -13648825.0817 4552130.7825 -13627575.5878 4565507.2624 mapzen_wms.xml test.tif
clhenrick
la source
Bien qu'il s'agisse d'une réponse utile, nous mettons déjà en cache les métadonnées de manière similaire, mais nous voulons savoir comment utiliser l'API VSI afin de pouvoir recadrer rapidement de petites portions de grandes images.
Skylion
Je ne sais pas si c'est parce que le point de terminaison de l'API Mapzen est un WMS en mosaïque, mais le code ci-dessus a été exécuté pour moi en moins d'une minute, êtes-vous sûr que l'API VSI sera plus rapide?
clhenrick
Nous travaillons avec de TRÈS grands rasters et de grands ensembles de données raster, le goulot d'étranglement est définitivement IO. De plus, les compartiments que nous utilisons sont privés et nécessitent des informations d'identification, ce qui signifie que l'utilisation de l'API http S3 ne fonctionnera pas dans notre cas. Ce n'est pas que nous devons lire chaque image, c'est que nous savons que nous devons chier une petite partie d'une très grande image.
Skylion
0

Je ne connais pas grand-chose aux compartiments S3, mais il semble que ce soit un lecteur de stockage cloud avec authentification utilisant les services REST http. c'est-à-dire pourrait être utilisé comme un point de montage ordinaire, avec un uri associé.

Si vous cherchez à recadrer des parties d'images / raster, le fichier doit être dans un format approprié.

Jetez un œil à la spécification TMS http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification

(Peut-être que netCDF pourrait également faire l'affaire.)

GDAL lit et écrit également des formats TMS. Fondamentalement, ce n'est qu'une structure de répertoires standard avec certains fichiers de métadonnées.

Maintenant, l'astuce consiste à créer à la volée l'URL avec les paramètres d'étendue géographique via le pilote TMS.

Jetez un œil à la documentation du pilote OpenLayers TMS: http://dev.openlayers.org/docs/files/OpenLayers/Layer/TMS-js.html Pour voir comment il gère les requêtes en fonction de l'emplacement, du zoom et de l'étendue.

Bien sûr, cela peut être fait en Python. Vous devez d'abord créer l'URI "point de montage" (ou chemin) approprié avec viscurl (selon la documentation), puis, une fois monté, accédez à la tuile spécifique conformément à la spécification TMS (qui est une extension du chemin) .

Juan
la source
Je viens d'ajouter quelques clarifications pour le différencier de l'utilisation de l'interface S3 en Python.
Skylion