Jak skutecznie uzyskiwać dostęp do plików za pomocą GDAL z segmentu S3 za pomocą VSIS3?

19

GDAL niedawno dodał nową funkcję, która pozwala na losowy odczyt plików segmentu S3. Chcę przyciąć obrazy GDAL z wielu kafelków obrazu bez konieczności pobierania całego pliku. Widziałem tylko bardzo rzadką dokumentację, jak skonfigurować i uzyskiwać dostęp do segmentu S3 przez GDAL i jestem trochę zdezorientowany, jak zacząć? Czy ktoś byłby na tyle uprzejmy, aby podać wyjątkowo krótki przykład / samouczek na temat ustawiania wirtualnego systemu plików dla GDAL, aby osiągnąć ten cel? Bonus pts, jeśli twoje rozwiązanie pozwala na skryptowanie go w Pythonie!

Aby wyjaśnić: już to zrobiliśmy w Pythonie. Problem z Pythonem polega na tym, że musisz pobrać cały obraz, aby go obsługiwać. Najnowsza wersja GDAL ma obsługę montażu łyżki S3, dzięki czemu jeśli chcemy powiedzieć przycięcie niewielkiej części obrazu, możemy operować bezpośrednio na tej mniejszej części. Niestety, ponieważ funkcja ta została wydana tylko w stabilnym oddziale w styczniu, nie znalazłem żadnej dokumentacji na jej temat. Tak więc rozwiązanie powinno wykorzystywać system VSI3 w najnowszej wersji GDAL lub w inny sposób inteligentnie korzysta z systemu, aby uniemożliwić użytkownikowi pobranie całego obrazu na dysk EBS w celu jego obsługi.

Oznacza to, że nagroda zostanie przyznana za odpowiedź, która korzysta z interfejsów API VSI znalezionych w najnowszych wersjach GDAL, dzięki czemu cały plik nie musi być wczytywany do pamięci lub dysku. Ponadto my, wiadra, których używamy, nie zawsze są publiczne, więc wiele opublikowanych sztuczek HTTP nie będzie działać w wielu naszych sytuacjach.

Skylion
źródło
Brak doświadczenia z S3 / buckets, ale ten post może być interesujący: link . Użyto podobnie (?)
cm1
@ cm1 Dziękujemy, że dokumentacja była jak dotąd najlepszą pomocą.
Skylion
Miło to słyszeć. Myślę, że to świetne pytanie, które zadałeś i uważnie obserwuję. Mam nadzieję, że Ty / inni rozwiążesz i opublikujesz tutaj fajne rozwiązanie!
cm1

Odpowiedzi:

18

Odkryłem, że gdy coś nie jest szczególnie dobrze udokumentowane w GDAL, przeglądanie ich testów może być przydatne.

/vsis3Moduł testowy ma kilka prostych przykładów, chociaż nie ma żadnych przykładów faktycznie czytanie fragmentów.

Zebrałem poniższy kod w oparciu o moduł testowy, ale nie jestem w stanie przetestować, ponieważ GDAL / vsis3 wymaga poświadczeń i nie mam konta 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)
użytkownik2856
źródło
2
Woot działa jak urok! Oto przykład przycinania z wiersza polecenia 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.b from_s3.tif
Skylion
Jak wyglądają te wartości, które ukryłeś? Myślę, że KEY_ID to krótki ciąg tekstowy, na przykład nazwa użytkownika. Co to jest ACCESS_KEY? Wygląda na to, że znajduje się w pliku pem, ale ma około 1000 znaków, więc musi to być coś innego.
Solx,
Będą to ciągi znaków z cyframi i literami, takie jak nazwa użytkownika i hasło. Możesz uzyskać te ciągi, ustawiając role IAM w AWS
RutgerH
10

Ponieważ /vsis3/jest zaimplementowany w GDAL, możesz także używać rasteriodo odczytu Windows zestawów danych S3. Wymaga to skonfigurowania poświadczeń dla boto lub korzystania z modułu obsługi sesji 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.

Zobacz także dokumenty rasterios windowed -rw i VSI .

Kersten
źródło
1

Spróbuj użyć pliku XML do przechowywania informacji WMS, więcej szczegółów znajduje się w dokumentacji GDAL WMS .

Oto przykładowy plik XML WMS do pobierania danych z interfejsu API Elevation 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>

Następnie możesz przypiąć do ramki granicznej w następujący sposób:

gdalwarp -of "GTiff" -te -13648825.0817 4552130.7825 -13627575.5878 4565507.2624 mapzen_wms.xml test.tif
Clhenrick
źródło
Chociaż jest to przydatna odpowiedź, już buforujemy metadane w podobny sposób, ale chcemy wiedzieć, jak korzystać z VSI API, abyśmy mogli szybko przycinać małe porcje dużych obrazów.
Skylion
Nie jestem pewien, czy to dlatego, że punkt końcowy interfejsu API Mapzen to WMS z kafelkami, ale powyższy kod działał dla mnie w niecałą minutę, czy jesteś pewien, że interfejs VSI API będzie działał szybciej?
clhenrick
Pracujemy z BARDZO dużymi rastrami i dużymi zestawami danych rastrowych, wąskim gardłem jest zdecydowanie IO. Także używane przez nas wiadra są prywatne i wymagają poświadczeń, co oznacza, że ​​używanie S3 HTTP API nie będzie działać w naszym przypadku. Nie chodzi o to, że musimy czytać każdy obraz, ale o to, że wiemy, że musimy skreślić małą część bardzo dużego obrazu.
Skylion
0

Nie wiem dużo o segmentach S3, ale wygląda na to, że jest to pamięć masowa w chmurze z uwierzytelnianiem za pomocą usług HTTP REST. tzn. może być stosowany jako zwykły punkt montażowy z powiązanym urim.

Jeśli szukasz przycinania części obrazów / rastra, plik musi mieć odpowiedni format.

Spójrz na specyfikację TMS http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification

(Być może netCDF może również załatwić sprawę.)

GDAL odczytuje i zapisuje również formaty TMS. Zasadniczo jest to tylko standardowa struktura katalogów z niektórymi plikami metadanych.

Teraz sztuką jest tworzenie w locie adresu URL z parametrami zasięgu geograficznego za pośrednictwem sterownika TMS.

Zobacz dokumentację sterownika OpenLayers TMS: http://dev.openlayers.org/docs/files/OpenLayers/Layer/TMS-js.html Aby zobaczyć, jak obsługuje żądania na podstawie lokalizacji, powiększenia i zakresu.

Oczywiście można to zrobić w Pythonie. Najpierw musisz utworzyć odpowiedni „punkt montowania” (lub ścieżkę) identyfikatora URI z wiskurem (zgodnie z dokumentacją), a następnie, po zamontowaniu, przejdź do konkretnego kafelka zgodnie ze specyfikacją TMS (będącą przedłużeniem ścieżki) .

Juan
źródło
Właśnie dodałem kilka wyjaśnień, aby odróżnić to od zwykłego używania interfejsu S3 w Pythonie.
Skylion