Se hai bisogno di una maggiore flessibilità per caricare immagini in Google Earth Engine (EE) rispetto a quanto fornito dall'interfaccia utente dell'editor di codice o dal comando upload
dello strumento a riga di comando "earthengine", puoi farlo descrivendo un caricamento di immagini utilizzando un file JSON noto come "manifest" e utilizzando il comando upload image --manifest
dello strumento a riga di comando.
Consulta un esempio completo in questo notebook di Colab che mostra il caricamento dei riquadri di immagini come singolo asset utilizzando un manifest.
Configurazione una tantum
- I caricamenti dei manifest funzionano solo con i file in Google Cloud Storage. Per iniziare a utilizzare Google Cloud Storage, crea un progetto Google Cloud, se non ne hai già uno. Tieni presente che la configurazione richiede la specifica di una carta di credito per la fatturazione. Al momento EE non addebita alcun costo, ma il trasferimento dei file su Google Cloud Storage prima del caricamento su EE comporta un piccolo costo. Per dimensioni dei dati di caricamento tipicamente elevate (decine o centinaia di gigabyte), il costo sarà piuttosto basso.
- Nel progetto, abilita l'API Cloud Storage e crea un bucket.
- Installa il client Earth Engine per Python. Include lo strumento a riga di comando
earthengine
, che useremo per caricare i dati. - Per i caricamenti automatici, ti consigliamo di utilizzare un service account Google Cloud associato al tuo progetto. Non è necessario un account di servizio per i test, ma quando hai tempo, inizia a familiarizzare con il loro utilizzo.
I file di origine di grandi dimensioni (100 GB o più) potrebbero essere caricati più velocemente se vengono suddivisi in più riquadri.
ID e nomi delle risorse
Per gli asset di proprietà del progetto Cloud, utilizza questa convenzione per i nomi degli asset:
projects/some-project-id/assets/some-asset-id
.
Informazioni sui nomi degli asset per i progetti precedenti e gli asset di proprietà dell'utente
Per i progetti precedenti, il nome della risorsa nel manifest deve essere leggermente diverso dall'ID risorsa visibile altrove in Earth Engine. Per caricare asset i cui ID iniziano con
users/some_user
o projects/some_project
, al nome della risorsa nel
manifest deve essere anteposta la stringa projects/earthengine-legacy/assets/
all'ID. Ad esempio, l'ID risorsa EE users/username/my_geotiff
deve essere caricato
utilizzando il nome projects/earthengine-legacy/assets/users/username/my_geotiff
.
Sì, questo significa che ID come projects/some_projects/some_asset
vengono
convertiti in nomi in cui projects
viene menzionato due volte:
projects/earthengine-legacy/assets/projects/some_projects/some_asset
.
Questo può creare confusione, ma è necessario per rispettare gli standard delle API Google Cloud.
Utilizzo dei manifest
Un manifest di base è mostrato nel seguente blocco di codice. Carica un file denominato
small.tif
da un bucket Google Cloud Storage denominato
gs://earthengine-test
.
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://earthengine-test/small.tif" ] } ] } ] }
Per utilizzarlo, salvalo in un file denominato manifest.json
ed esegui:
earthengine upload image --manifest /path/to/manifest.json
Il file gs://earthengine-test/small.tif
esiste ed è
pubblicamente leggibile, puoi utilizzarlo per i test.
Insiemi di riquadri
La struttura del manifest JSON, un po' complicata, è necessaria per offrire sufficiente flessibilità per risolvere un problema comune di caricamento: come descrivere tutti i modi possibili per combinare i pixel di più file di origine in un unico asset. Nello specifico, esistono due modi indipendenti per raggruppare i file:
- Mosaici. A volte più file rappresentano più riquadri (ad esempio, ogni riquadro è un quadrato di 1 x 1 grado). Questi file devono essere mosaici (uniti) nella stessa banda in una risorsa EE.
- Cinturini separati. A volte, più file rappresentano più bande. Questi file devono essere impilati come bande in una risorsa EE.
È possibile che sia necessario utilizzare entrambi i metodi contemporaneamente, ma si tratta di una situazione rara.
Per descrivere queste opzioni, i manifest introducono il concetto di tileset. Un singolo set di tessere corrisponde a una singola origine GDAL. Per questo motivo, tutte le origini in un singolo set di tessere devono avere la stessa struttura GDAL (numero e tipo di bande, proiezione, trasformazione, valore mancante). Poiché un'origine GDAL può avere più bande, un set di tessere può contenere dati per più bande EE.
Per l'importazione di mosaici, il manifest sarà simile al seguente:
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/N30W22.tif" ] }, { "uris": [ "gs://bucket/N31W22.tif" ] } ] } ] }
Per i gruppi separati, il manifest sarà simile a questo (devi anche aggiungere una sezione bands
come spiegato di seguito):
{ "name": "projects/some-project-id/assets/some-asset-id", "bands": ..., "tilesets": [ { "id": "tileset_for_band1", "sources": [ { "uris": [ "gs://bucket/band1.tif" ] } ] }, { "id": "tileset_for_band2", "sources": [ { "uris": [ "gs://bucket/band2.tif" ] } ] } ] }
Tieni presente che, nel caso di bande separate, dobbiamo assegnare a ogni set di tessere un ID set di tessere diverso per chiarezza. L'ID set di tessere può essere una stringa arbitraria. Queste stringhe non vengono conservate nell'asset caricato. Gli ID set di riquadri vengono utilizzati solo durante l'importazione per distinguerli tra loro.
Cinturini
Il secondo concetto importante è la corrispondenza dei file di origine alle bande di asset EE.
Questo viene fatto utilizzando la sezione bands
del manifest.
La sezione bands
può essere omessa, nel qual caso le bande vengono create prima
dai file del primo set di tessere, poi dal set di tessere successivo e così via.
Per impostazione predefinita, le bande sono denominate "b1", "b2" e così via. Per sostituire i nomi predefiniti delle bande, includi
una sezione "bands" alla fine, come segue:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/rgb.tif" ] } ] } ], "bands": [ { "id": "R", "tilesetBandIndex": 0 }, { "id": "G", "tilesetBandIndex": 1 }, { "id": "B", "tilesetBandIndex": 2 } ] }
Il numero di bande EE deve essere uguale al numero totale di bande in tutti i set di tessere.
Se non vuoi importare tutti i canali di un file, puoi utilizzare il
tilesetBandIndex
campo per indicare quali bande GDAL devono essere importate.
La prima banda ha tilesetBandIndex pari a 0.
Esempio:
Supponiamo che il file di origine abbia quattro bande: "tmin", "tmin_error", "tmax", "tmax_error". Vogliamo importare solo "tmin" e "tmax". Le sezioni manifest pertinenti avranno il seguente aspetto:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "temperature", "sources": [ { "uris": [ "gs://bucket/temperature.tif" ] } ] } ], "bands": [ { "id": "tmin", "tilesetBandIndex": 0, "tilesetId": "temperature" }, { "id": "tmax", "tilesetBandIndex": 2, "tilesetId": "temperature" } ] }
Fasce per maschere
Il mascheramento delle bande è controllato dal componente maskBands
del manifest.
Sono supportate tre possibili configurazioni della maschera (ma si presume sempre che la banda della maschera sia l'ultima banda di un determinato file).
- Maschera per tutte le bande di dati nello stesso file.
- Maschera per tutte le bande di dati provenienti da tutti gli altri file.
- Maschera per alcune bande di dati.
1. Il caso più comune è un singolo file GeoTIFF la cui ultima banda viene utilizzata come maschera per le altre bande. Questo funziona solo per i file GeoTIFF di tipo Byte. Utilizza il seguente manifest:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "data_tileset" } ] }
2. Per utilizzare un file GeoTIFF maschera come maschera per tutti i canali di un altro file GeoTIFF, utilizza il seguente manifest:
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] }, { "id": "mask_tileset", "sources": [ { "uris": [ "gs://bucket/mask_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "mask_tileset" } ] }
3. Per utilizzare un file GeoTIFF come maschera per una banda specifica in un altro file, utilizza il
seguente manifest (la differenza rispetto al caso precedente è che il
campo bandIds
in maskBands
è impostato):
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "id": "data_tileset", "sources": [ { "uris": [ "gs://bucket/data_file.tif" ] } ] }, { "id": "mask_tileset", "sources": [ { "uris": [ "gs://bucket/mask_file.tif" ] } ] } ], "bands": [ { "id": "data_band", "tilesetId": "data_tileset" }, { "id": "qa_band", "tilesetId": "data_tileset" } ], "maskBands": [ { "tilesetId": "mask_tileset", "bandIds": ["data_band"] } ] }
Nell'ultimo esempio, utilizziamo due bande del
tileset data_tileset
, ma applichiamo una maschera solo a una delle bande
(data_band
), come indicato dal campo bandIds
dell'unico
oggetto elenco maskBands
fornito.
Tieni presente che solo l'ultima banda del set di tessere menzionata in maskBands
viene utilizzata come banda della maschera.
Norme relative al sistema piramidale
Quando Earth Engine costruisce
piramidi di immagini
durante l'importazione, deve ridurre ripetutamente le griglie di 2 x 2 pixel in un singolo pixel,
trasformando il valore del pixel in qualche modo. Per impostazione predefinita, i valori dei pixel vengono mediati, il che è la cosa giusta da fare nella maggior parte dei casi quando la banda raster rappresenta dati più o meno continui. Tuttavia, esistono due situazioni in cui l'utilizzo del valore predefinito produrrà risultati errati. In questo caso, il campo pyramidingPolicy
nella definizione della fascia deve essere impostato (se non è impostato, per impostazione predefinita il valore è "MEDIA").
Per la classificazione delle immagini raster (ad esempio per la classificazione della copertura del suolo), il modo più logico per creare una piramide di pixel è prendere la maggior parte dei quattro valori per produrre quello successivo. Questo viene fatto utilizzando il criterio di piramidizzazione "MODE":
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/landcover.tif" ] } ] } ], "bands": [ { "id": "landcover", "pyramidingPolicy": "MODE" } ] }
Per le bande raster in cui né "MEDIA" né "MODA" hanno senso (ad esempio i pixel con imballaggio di bit), deve essere utilizzata la regola di piramidizzazione "SAMPLE". "SAMPLE" assume sempre il valore del pixel in alto a sinistra di ogni griglia 2x2. L'esempio seguente assegna il criterio di piramidizzazione"MEDIA" a una banda che rappresenta una variabile continua ("NDVI ") e"SAMPLE" alla banda "QA" dei dati.
{ "name": "projects/earthengine-legacy/assets/users/username/some_folder/some_id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/ndvi.tif" ] } ] } ], "bands": [ { "id": "NDVI", "tilesetBandIndex": 0, "pyramidingPolicy": "MEAN" }, { "id": "QA", "tilesetBandIndex": 1, "pyramidingPolicy": "SAMPLE" } ] }
Ora di inizio e ora di fine
Per tutti gli asset è necessario specificare l'ora di inizio e di fine per fornire un contesto più ampio ai dati, soprattutto se sono inclusi nelle raccolte. Questi campi non sono obbligatori, ma ti consigliamo vivamente di utilizzarli, se possibile.
In genere, l'ora di inizio e di fine indica l'ora dell'osservazione, non l'ora in cui è stato prodotto il file di origine.
Per semplicità, l'ora di fine viene trattata come un confine esclusivo. Ad esempio, per gli asset che coprono esattamente un giorno, utilizza la mezzanotte di due giorni consecutivi (ad esempio 1980-01-31T00:00:00 e 1980-02-01T00:00:00) per l'ora di inizio e di fine. Se la risorsa non ha durata, imposta l'ora di fine uguale a quella di inizio. Rappresenta le ore nei manifest come stringhe ISO 8601. Per semplificare i valori della data, ti consigliamo di assumere che l'ora di fine sia esclusa (ad esempio, la mezzanotte del giorno successivo per gli asset giornalieri).
Esempio:
{ "name": "projects/some-project-id/assets/some-asset-id", "tilesets": [ { "sources": [ { "uris": [ "gs://bucket/img_20190612.tif" ] } ] } ], "startTime": "1980-01-31T00:00:00Z", "endTime": "1980-02-01T00:00:00Z" }
Riferimento alla struttura del manifest
La seguente struttura JSON include tutti i possibili campi del manifest per il caricamento delle immagini. Trova le definizioni dei campi nella seguente sezione Definizioni dei campi del manifest.
{ "name": <string>, "tilesets": [ { "dataType": <string>, "id": <string>, "crs": <string>, "sources": [ { "uris": [ <string> ], "affineTransform": { "scaleX": <double>, "shearX": <double>, "translateX": <double>, "shearY": <double>, "scaleY": <double>, "translateY": <double> } } ] } ], "bands": [ { "id": <string>, "tilesetId": <string>, "tilesetBandIndex": <int32>, "missingData": { "values": [<double>] }, "pyramindingPolicy": <string> } ], "maskBands": [ { "tilesetId": <string>, "bandIds": [ <string> ] } ], "footprint": { "points": [ { "x": <double>, "y": <double> } ], "bandId": <string> }, "missingData": { "values": [<double>] }, "pyramidingPolicy": <string>, "uriPrefix": <string>, "startTime": { "seconds": <integer> }, "endTime": { "seconds": <integer> }, "properties": { <unspecified> } }
Definizioni dei campi del manifest
nome
string
Il nome dell'asset da creare.
name
sia nel formato "projects/*/assets/**"
(ad esempio, "projects/earthengine-legacy/assets/users/USER/ASSET").
set di riquadri
list
Un elenco di dizionari che definiscono le proprietà per i set di riquadri.
Per ulteriori informazioni, consulta i seguenti campi elemento del dizionario tilesets
.
tilesets[i].dataType
string
Specifica il tipo di dati numerici dei dati. Il valore predefinito è il tipo registrato da GDAL, nel qual caso non è necessario definirlo.
Tipo di dati | Valore |
---|---|
Non specificato | "DATA_TYPE_UNSPECIFIED" |
Numero intero a 8 bit con segno | "INT8" |
Numero intero non firmato a 8 bit | "UINT8" |
Numero intero a 16 bit con segno | "INT16" |
Numero intero non firmato a 16 bit | "UINT16" |
Numero intero a 32 bit con segno | "INT32" |
Numero intero non firmato a 32 bit | "UINT32" |
Virgola mobile a 32 bit | "FLOAT32" |
Virgola mobile a 64 bit | "FLOAT64" |
tilesets[i].id
string
L'ID del set di tessere. Deve essere univoco tra i set di tessere specificati nel manifest dell'asset. Questo ID viene ignorato durante la fase di elaborazione; viene utilizzato solo per collegare un set di tessere a una banda. La stringa vuota è un ID valido.
tilesets[i].crs
string
Il sistema di riferimento delle coordinate della griglia di pixel, specificato come codice standard, se possibile (ad esempio, codice EPSG), e in formato WKT in caso contrario.
tilesets[i].sources
list
Un elenco di dizionari che definiscono le proprietà di un file immagine e dei relativi file sidecar. Per ulteriori informazioni, consulta i seguenti campi elemento del dizionario sources
.
tilesets[i].sources[j].uris
list
Un elenco di URI dei dati da importare. Sono supportati solo gli URI Google Cloud Storage. Ogni URI deve essere specificato nel seguente formato:
gs://bucket-id/object-id
.
L'oggetto principale deve essere il primo elemento dell'elenco e i sidecar devono essere elencati successivamente. A ogni URI viene anteposto il prefisso
ImageManifest.uriPrefix
, se impostato.
tilesets[i].sources[j].affineTransform
dictionary
Una trasformazione affine facoltativa. Deve essere specificato solo se i dati di
uris
(inclusi eventuali sidecar) non sono sufficienti per posizionare i pixel.
Fornito come dizionario con le seguenti chiavi:
"scaleX", "shearX", "translateX", "shearY", "scaleY", "translateY".
Per ulteriori informazioni, consulta
questa risorsa.
Chiavi e valori di esempio:
{ "scaleX": 0.1, "shearX": 0.0, "translateX": -180.0, "shearY": 0.0, "scaleY": -0.1, "translateY": 90.0 }
cinturini
list
Un elenco di dizionari che definiscono le proprietà di una singola banda proveniente da un set di tessere.
Tieni presente che l'ordine delle bande dell'asset corrisponde a quello di bands
.
Per ulteriori informazioni, consulta i seguenti campi elemento del dizionario bands
.
bands[i].id
string
L'ID (nome) del gruppo.
bands[i].tilesetId
string
L'ID del set di tessere corrispondente alla banda.
bands[i].tilesetBandIndex
int32
L'indice banda a partire da zero del set di tessere corrispondente alla banda.
bands[i].missingData.values
list
Un elenco di valori (tipo double) che non rappresentano dati nella banda.
bands[i].pyramidingPolicy
string
Le norme relative al sistema piramidale. Per ulteriori informazioni, visita questo link. Le opzioni disponibili sono le seguenti:
- "MEDIA" (valore predefinito)
- "MODE"
- "SAMPLE"
maskBands
list
Un elenco di dizionari che definiscono le proprietà di una singola banda di maschera proveniente da un set di tessere.
È possibile fornire al massimo una fascia per la mascherina.
Per ulteriori informazioni, consulta i seguenti campi elemento del dizionario maskBands
.
maskBands[i].tilesetId
string
L'ID del set di tessere corrispondente alla banda della maschera. L'ultima banda del tileset viene sempre utilizzata come banda della maschera.
maskBands[i].bandIds
list of strings
Elenco degli ID delle bande a cui si applica la banda maschera. Se è vuoto, la banda della maschera viene applicata a tutte le bande dell'asset. Ogni banda può avere una sola banda di maschera corrispondente.
impronta
dictionary
Un dizionario che definisce le proprietà dell'impronta di tutti i pixel validi in un'immagine.
Se è vuoto, l'impronta predefinita è l'intera immagine. Per ulteriori informazioni, consulta i seguenti campi dell'elemento del dizionario footprint
.
footprint.points
list
Un elenco di punti che definiscono l'impronta di tutti i pixel validi in un'immagine. Un punto
è definito da un dizionario con le chiavi "x" e "y" con valori float. Un elenco di punti deve descrivere un anello che forma l'esterno di un semplice poligono che deve contenere i centri di tutti i pixel validi dell'immagine. Deve essere un anello lineare: l'ultimo punto deve essere uguale al primo. Le coordinate sono nella proiezione della banda specificata da bandId
.
Nota: utilizza coordinate non intere come il centro di ogni pixel perché
footprint
è considerato come un pixel se il pixel (un rettangolo 1x1)
interseca l'impronta. Per evitare di selezionare accidentalmente i pixel adiacenti, non utilizzare coordinate con valori interi, in quanto si tratta dei confini tra i pixel. Disegnare l'impronta lungo i centri dei pixel
impedisce di includere pixel indesiderati, che possono causare errori quando i pixel previsti
sono adiacenti a un confine della mappa, ad esempio l'antimeridiano o un polo.
Ad esempio, per un'immagine 2 x 2 con tutti e quattro i pixel validi, di seguito è riportato un possibile anello:
[ { "x": 0.5, "y": 0.5 }, { "x": 0.5, "y": 1.5 }, { "x": 1.5, "y": 1.5 }, { "x": 1.5, "y": 0.5 }, { "x": 0.5, "y": 0.5 } ]
footprint.bandId
string
L'ID della banda il cui sistema di riferimento cartografico definisce le coordinate dell'impronta. Se è vuoto, viene utilizzata la prima banda.
missingData.values
list
Un elenco di valori (tipo double) che non rappresentano dati in tutte le bande dell'immagine. Si applica a
tutti i gruppi che non specificano un proprio missingData
.
pyramidingPolicy
string
Le norme relative al sistema piramidale. Se non specificato, il criterio "MEDIA" viene applicato per impostazione predefinita. Si applica a tutti i gruppi che non ne specificano uno proprio. Per ulteriori informazioni, visita questo link. Le opzioni disponibili sono le seguenti:
- "MEDIA" (valore predefinito)
- "MODE"
- "SAMPLE"
uriPrefix
string
Un prefisso facoltativo anteposto a tutti i uris
definiti nel manifest.
startTime
integer
Il timestamp associato alla risorsa, se presente. In genere corrisponde all'ora in cui è stata acquisita un'immagine satellitare. Per gli asset che corrispondono a un intervallo di tempo, ad esempio i valori medi su un mese o un anno, questo timestamp corrisponde all'inizio dell'intervallo. Specificato come secondi e (facoltativamente) nanosecondi dall'epoca (1970-01-01). Si presume che sia nel fuso orario UTC.
endTime
integer
Per gli asset che corrispondono a un intervallo di tempo, ad esempio i valori medi su un mese o un anno, questo timestamp corrisponde alla fine dell'intervallo (esclusivo). Specificato come secondi e (facoltativamente) nanosecondi dall'epoca (1970-01-01). Si presume che sia nel fuso orario UTC.
proprietà
dictionary
Un dizionario piatto arbitrario di coppie chiave/valore. Le chiavi devono essere stringhe e i valori possono essere numeri o stringhe. I valori di elenco non sono ancora supportati per gli asset caricati dagli utenti.
Limitazioni
Dimensioni del file manifest JSON
La dimensione massima del file manifest JSON è 10 MB. Se hai molti file da caricare,
valuta la possibilità di ridurre il numero di caratteri necessari per descrivere il set di dati. Ad esempio,
utilizza il campo uriPrefix
per eliminare
la necessità di fornire il percorso del bucket Google Cloud per ogni URI nell'elenco
uris
. Se è necessaria un'ulteriore riduzione delle dimensioni, prova ad abbreviare i nomi file.
Formato file immagine
Ogni file immagine deve essere un'immagine TIFF. Se il sistema di riferimento cartografico non è specificato nel file manifest, il file deve essere un file GeoTIFF con un sistema di riferimento cartografico incorporato.
I file TIFF possono essere compressi con DEFLATE, JPEG-XL/JXL, LERC, LERC_DEFLATE, LERC_ZSTD, LZMA, LZW, WEBP o ZSTD.
Consigli per un'esperienza di caricamento ottimale per i file di grandi dimensioni:
- Scelta migliore:ZSTD offre un buon equilibrio tra velocità e compressione.
- Da evitare: LZMA può essere molto lento nonostante una buona compressione.
- File non compressi: i file saranno più grandi e i tempi di caricamento più lunghi.
- Compressione con perdita di dati (ad es. JPEG): potrebbero essere alterati i valori dei pixel. Utilizza la compressione senza perdita di dati (ad es. DEFLATE, LZMA, LZW, ZSTD) a meno che tu non ne comprenda il potenziale impatto sui tuoi dati.