Le immagini che compongono un ImageCollection
possono essere visualizzate come un'animazione o una serie di miniature denominate "filmstrip". Questi metodi consentono di valutare rapidamente i contenuti di un ImageCollection
e rappresentano un mezzo efficace per osservare i cambiamenti spazio-temporali (Figura 1).
getVideoThumbURL()
produce una serie di immagini animategetFilmstripThumbURL()
genera una serie di immagini in miniatura
Le sezioni seguenti descrivono come preparare un ImageCollection
per la visualizzazione, forniscono codice di esempio per ogni metodo di visualizzazione della raccolta e illustrano diverse tecniche di animazione avanzate.
Figura 1. Animazione che mostra la progressione di tre giorni di uragani atlantici a
settembre 2017.
Preparazione della raccolta
Filtra, componi, ordina e applica stili alle immagini all'interno di una raccolta per visualizzare solo quelle di tuo interesse o mettere in evidenza un fenomeno. Qualsiasi ImageCollection
può essere fornito come input alle funzioni di visualizzazione, ma una raccolta selezionata che tenga conto di intervalli di date inter e intraannuali, intervallo di osservazione, estensione regionale, qualità e rappresentazione può ottenere risultati migliori.
Filtri
Filtra una raccolta di immagini in modo da includere solo i dati pertinenti che supportano lo scopo della visualizzazione. Prendi in considerazione date, estensione spaziale, qualità e altre proprietà specifiche di un determinato set di dati.
Ad esempio, filtra una raccolta di dati sulla riflettanza superficiale di Sentinel-2 in base a:
un singolo intervallo di date.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterDate('2018-01-01', '2019-01-01');
un intervallo di giorni dell'anno seriale,
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filter(ee.Filter.calendarRange(171, 242, 'day_of_year'));
una regione di interesse.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2));
o una proprietà immagine.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 50));
Concatenare più filtri.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterDate('2018-01-01', '2019-01-01') .filterBounds(ee.Geometry.Point(-122.1, 37.2)) .filter('CLOUDY_PIXEL_PERCENTAGE < 50');
Composizione
Intervalli di date intra- e interannuali compositi per ridurre il numero di immagini in una raccolta e migliorare la qualità. Ad esempio, supponiamo che tu debba creare una visualizzazione dell'Indice di vegetazione di Normalizzato annuale per l'Africa. Un'opzione è semplicemente filtrare una raccolta NDVI di 16 giorni di MODIS in modo da includere tutte le osservazioni del 2018.
Editor di codice (JavaScript)
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2') .filterDate('2018-01-01', '2019-01-01') .select('NDVI');
Composto interannuale per filtro e riduzione
La visualizzazione della raccolta sopra indicata mostra un rumore considerevole nelle regioni boscate con una copertura nuvolosa elevata (Figura 2a). È possibile ottenere una rappresentazione migliore riducendo gli intervalli di date seriali in base alla mediana per tutti gli anni della raccolta MODIS.
Editor di codice (JavaScript)
// Make a day-of-year sequence from 1 to 365 with a 16-day step. var doyList = ee.List.sequence(1, 365, 16); // Import a MODIS NDVI collection. var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2').select('NDVI'); // Map over the list of days to build a list of image composites. var ndviCompList = doyList.map(function(startDoy) { // Ensure that startDoy is a number. startDoy = ee.Number(startDoy); // Filter images by date range; starting with the current startDate and // ending 15 days later. Reduce the resulting image collection by median. return ndviCol .filter(ee.Filter.calendarRange(startDoy, startDoy.add(15), 'day_of_year')) .reduce(ee.Reducer.median()); }); // Convert the image List to an ImageCollection. var ndviCompCol = ee.ImageCollection.fromImages(ndviCompList);
L'animazione risultante da questa raccolta è meno rumorosa, poiché ogni immagine rappresenta la mediana di un composito NDVI di 16 giorni per oltre 20 anni di dati (Figura 1b). Guarda questo tutorial per ulteriori informazioni su questa animazione.
Figura 2a. NDVI annuale senza composizione interannuale. | Figura 2b. NDVI annuale con composizione interannuale. |
Composto intra-annuale per filtro e riduzione
L'esempio precedente applica il compositing interannuale. Può essere utile anche compilare una serie di osservazioni intraannuali. Ad esempio, i dati di Landsat vengono raccolti ogni sedici giorni per una determinata scena per sensore, ma spesso alcune parti delle immagini sono oscurate dalle nuvole. Mascherare le nuvole e comporre più immagini della stessa stagione può produrre una rappresentazione più libera dalle nuvole. Prendi in considerazione il seguente esempio in cui le immagini Landsat 5 di luglio e agosto vengono composite utilizzando la mediana per ogni anno dal 1985 al 2011.
Editor di codice (JavaScript)
// Assemble a collection of Landsat surface reflectance images for a given // region and day-of-year range. var lsCol = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2') .filterBounds(ee.Geometry.Point(-122.9, 43.6)) .filter(ee.Filter.dayOfYear(182, 243)) // Add the observation year as a property to each image. .map(function(img) { return img.set('year', ee.Image(img).date().get('year')); }); // Define a function to scale the data and mask unwanted pixels. function maskL457sr(image) { // Bit 0 - Fill // Bit 1 - Dilated Cloud // Bit 2 - Unused // Bit 3 - Cloud // Bit 4 - Cloud Shadow var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0); var saturationMask = image.select('QA_RADSAT').eq(0); // Apply the scaling factors to the appropriate bands. var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2); var thermalBand = image.select('ST_B6').multiply(0.00341802).add(149.0); // Replace the original bands with the scaled ones and apply the masks. return image.addBands(opticalBands, null, true) .addBands(thermalBand, null, true) .updateMask(qaMask) .updateMask(saturationMask); } // Define a list of unique observation years from the image collection. var years = ee.List(lsCol.aggregate_array('year')).distinct().sort(); // Map over the list of years to build a list of annual image composites. var lsCompList = years.map(function(year) { return lsCol // Filter image collection by year. .filterMetadata('year', 'equals', year) // Apply cloud mask. .map(maskL457sr) // Reduce image collection by median. .reduce(ee.Reducer.median()) // Set composite year as an image property. .set('year', year); }); // Convert the image List to an ImageCollection. var lsCompCol = ee.ImageCollection.fromImages(lsCompList);
Composto intra-annuale per unione e riduzione
Tieni presente che i due metodi di composizione precedenti mappano un List
di giorni e
anni per definire in modo incrementale nuove date da filtrare e comporre.
L'applicazione di un join è un altro metodo per eseguire questa operazione. Nel
seguente snippet viene definita una raccolta di anni univoca, a cui viene applicata una saveAll
join per identificare tutte le immagini corrispondenti a un determinato anno.
Le immagini appartenenti a un determinato anno sono raggruppate in un oggetto List
che viene memorizzato come proprietà del rispettivo rappresentante dell'anno nella raccolta di anni distinti. I compositi annuali vengono generati da questi elenchi riducendo
ImageCollections
definito in una funzione mappata sulla raccolta distinta
dell'anno.
Editor di codice (JavaScript)
// Assemble a collection of Landsat surface reflectance images for a given // region and day-of-year range. var lsCol = ee.ImageCollection('LANDSAT/LT05/C02/T1_L2') .filterBounds(ee.Geometry.Point(-122.9, 43.6)) .filter(ee.Filter.dayOfYear(182, 243)) // Add the observation year as a property to each image. .map(function(img) { return img.set('year', ee.Image(img).date().get('year')); }); // Make a distinct year collection; one image representative per year. var distinctYears = lsCol.distinct('year').sort('year'); // Define a join filter; one-to-many join on ‘year’ property. var filter = ee.Filter.equals({leftField: 'year', rightField: 'year'}); // Define a join. var join = ee.Join.saveAll('year_match'); // Apply the join; results in 'year_match' property being added to each distinct // year representative image. The list includes all images in the collection // belonging to the respective year. var joinCol = join.apply(distinctYears, lsCol, filter); // Define a function to scale the data and mask unwanted pixels. function maskL457sr(image) { // Bit 0 - Fill // Bit 1 - Dilated Cloud // Bit 2 - Unused // Bit 3 - Cloud // Bit 4 - Cloud Shadow var qaMask = image.select('QA_PIXEL').bitwiseAnd(parseInt('11111', 2)).eq(0); var saturationMask = image.select('QA_RADSAT').eq(0); // Apply the scaling factors to the appropriate bands. var opticalBands = image.select('SR_B.').multiply(0.0000275).add(-0.2); var thermalBand = image.select('ST_B6').multiply(0.00341802).add(149.0); // Replace the original bands with the scaled ones and apply the masks. return image.addBands(opticalBands, null, true) .addBands(thermalBand, null, true) .updateMask(qaMask) .updateMask(saturationMask); } // Map over the distinct years collection to build a list of annual image // composites. var lsCompList = joinCol.map(function(img) { // Get the list of images belonging to the given year. return ee.ImageCollection.fromImages(img.get('year_match')) // Apply cloud mask. .map(maskL457sr) // Reduce image collection by median. .reduce(ee.Reducer.median()) // Set composite year as an image property. .copyProperties(img, ['year']); }); // Convert the image List to an ImageCollection. var lsCompCol = ee.ImageCollection(lsCompList);
Composito dello stesso giorno per unione e riduzione
Un altro caso di composizione è la creazione di mosaici di immagini spazialmente contigui. Supponiamo che la tua regione di interesse comprenda due righe Landsat nello stesso percorso e che il tuo obiettivo sia visualizzare un mosaico di immagini delle due immagini per ogni orbita di Landsat 8 nel 2017 e nel 2018. Qui, dopo aver filtrato la raccolta per percorso e riga, viene utilizzata un'operazione di join per creare un mosaico di immagini Landsat della stessa orbita, definita dalla data di acquisizione.
Editor di codice (JavaScript)
var lsCol = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') .filterDate('2017-01-01', '2019-01-01') .filter('WRS_PATH == 38 && (WRS_ROW == 28 || WRS_ROW == 29)') .map(function(img) { var date = img.date().format('YYYY-MM-dd'); return img.set('date', date); }); var distinctDates = lsCol.distinct('date').sort('date'); var filter = ee.Filter.equals({leftField: 'date', rightField: 'date'}); var join = ee.Join.saveAll('date_match'); var joinCol = join.apply(distinctDates, lsCol, filter); var lsColMos = ee.ImageCollection(joinCol.map(function(col) { return ee.ImageCollection.fromImages(col.get('date_match')).mosaic(); }));
Ordinamento
Ordina una raccolta per data per garantire la corretta sequenza cronologica o per una proprietà di tua scelta. Per impostazione predefinita, la serie di frame di visualizzazione è ordinata in ordine naturale della raccolta. La disposizione della serie può essere modificata utilizzando il metodo di raccolta sort
, in cui viene selezionata una proprietà Image
per l'ordinamento in ordine crescente o decrescente. Ad esempio, per ordinare in base all'ora di osservazione, utilizza la proprietà onnipresente system:time_start
.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2)) .sort('system:time_start');
In alternativa, l'ordine dovrebbe essere definito aumentando la nuvolosità, come in questo caso di immagini Sentinel-2.
Editor di codice (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2)) .sort('CLOUDY_PIXEL_PERCENTAGE');
L'ordine può essere definito anche da una proprietà derivata, ad esempio l'NDVI regionale medio. Qui, l'NDVI regionale viene aggiunto come proprietà a ogni immagine in una funzione mappata, seguita da una ordinamento in base alla nuova proprietà.
Editor di codice (JavaScript)
// Define an area of interest geometry. var aoi = ee.Geometry.Point(-122.1, 37.2).buffer(1e4); // Filter MODIS NDVI image collection by a date range. var ndviCol = ee.ImageCollection('MODIS/061/MOD13A1') .filterDate('2018-01-01', '2019-01-01') .select('NDVI') // Map over the image collection to calculate regional mean NDVI and add // the result to each image as a property. .map(function(img) { var meanNdvi = img.reduceRegion({ reducer: ee.Reducer.mean(), geometry: aoi, scale: 500}); return img.set('meanNdvi', meanNdvi.get('NDVI')); }) // Sort the collection by descending regional mean NDVI. .sort('meanNdvi', false);
Visualizzazione di immagini
La visualizzazione di immagini trasforma i numeri in colori. Esistono tre modi per controllare la modalità di rappresentazione dei dati delle immagini come colore nei metodi di visualizzazione delle raccolte:
- Fornisci gli argomenti di visualizzazione direttamente a
getVideoThumbURL
egetFilmstripThumbURL
. - Mappa il metodo immagine
visualize
alla raccolta di immagini prima dell'applicazione digetVideoThumbURL
egetFilmstripThumbURL
. - Mappa il metodo immagine
sldStyle
alla raccolta di immagini prima dell'applicazione digetVideoThumbURL
egetFilmstripThumbURL
. Per scoprire di più, consulta Descrittore livello stilizzato.
Gli esempi in questa guida utilizzano le opzioni 1 e 2, in cui la visualizzazione viene ottenuta mappando tre bande di immagini di un'immagine multibanda ai canali di colore rosso, verde e blu o graduando i valori di una singola banda in modo lineare lungo una tavolozza di colori. I parametri di visualizzazione includono:
Parametro | Descrizione | Tipo |
---|---|---|
bands | Elenco separato da virgole di tre nomi di bande da mappare a RGB | list |
min | Valori da mappare a 0 | numero o elenco di tre numeri, uno per ogni banda |
max | Valori da mappare a 255 | numero o elenco di tre numeri, uno per ogni banda |
guadagno | Valori per moltiplicare ogni valore del pixel | numero o elenco di tre numeri, uno per ogni banda |
bias | Valori da aggiungere a ogni DN | numero o elenco di tre numeri, uno per ogni banda |
gamma | Fattori di correzione gamma | numero o elenco di tre numeri, uno per ogni banda |
palette | Elenco di stringhe di colore in stile CSS (solo immagini a banda singola) | elenco di stringhe esadecimali separate da virgole |
opacity | L'opacità del livello (0,0 è completamente trasparente e 1,0 è completamente opaco) | numero |
Utilizza l'argomento bands
per selezionare le bande che vuoi visualizzare. Fornisci un elenco di uno o tre nomi di gruppi. Per quanto riguarda le immagini multibanda, per impostazione predefinita vengono selezionate le prime tre bande. L'ordine dei nomi dei gruppi determina l'assegnazione del colore. Il primo, il secondo e il terzo gruppo elencato sono mappati rispettivamente a rosso, verde e blu.
La scalabilità dell'intervallo di dati è un aspetto importante da considerare quando si visualizzano le immagini. Per impostazione predefinita, i valori dei dati a virgola mobile compresi tra 0 e 1 (inclusi) vengono scalati tra 0 e 255 (inclusi). I valori al di fuori di questo intervallo vengono forzati su 0 e
255, a seconda che siano inferiori a 0 o superiori a 1,
rispettivamente. Per quanto riguarda i dati interi, la capacità completa definita dal tipo viene scalata tra 0 e 255 (ad es. i dati a 16 bit con segno hanno un intervallo da -32.768 a 32.767, che viene scalato in [0, 255] per impostazione predefinita). Se accetti i valori predefiniti, spesso le visualizzazioni avranno poco o nessun contrasto tra le caratteristiche delle immagini. Utilizza min
e max
per migliorare il contrasto e mettere in evidenza un determinato intervallo di dati. Una buona regola empirica è impostare min
e max
su valori che rappresentano il 2° e il 98° percentile dei dati all'interno della tua area di interesse. Consulta il seguente esempio di calcolo di questi valori per un
modello digitale dell'elevazione.
Editor di codice (JavaScript)
// Import SRTM global elevation model. var demImg = ee.Image('USGS/SRTMGL1_003'); // Define a rectangular area of interest. var aoi = ee.Geometry.Polygon( [[ [-103.84153083119054, 49.083004219142886], [-103.84153083119054, 25.06838270664608], [-85.64817145619054, 25.06838270664608], [-85.64817145619054, 49.083004219142886] ]], null, false); // Calculate the 2nd and 98th percentile elevation values from rescaled (to // 500m) pixels intersecting the area of interest. A Dictionary is returned. var percentClip = demImg.reduceRegion({ reducer: ee.Reducer.percentile([2, 98]), geometry: aoi, scale: 500, maxPixels: 3e7 }); // Print the regional 2nd and 98th percentile elevation values. Get the // dictionary keys and use them to get the values for each percentile summary. var keys = percentClip.keys(); print('Set vis min to:', ee.Number(percentClip.get(keys.get(0))).round()); print('Set vis max to:', ee.Number(percentClip.get(keys.get(1))).round());
Il parametro palette
definisce i colori per rappresentare l'immagine di visualizzazione a 8 bit. Si applica solo alle rappresentazioni a banda singola.
Se lo specifichi con un'immagine multibanda, viene generato un errore.
Se i dati sono a banda singola o vuoi visualizzare una singola banda da un'immagine multibanda, imposta il parametro forceRgbOutput
su true
(non necessario se viene fornito l'argomento palette
). Utilizza i parametri min
e max
per
definire l'intervallo di valori da ridimensionare in modo lineare tra 0 e 255.
Di seguito è riportato un esempio di mappatura di una funzione di visualizzazione su una raccolta di immagini a banda singola. Viene importata una raccolta NDVI di MODIS, vengono impostati gli argomenti di visualizzazione per il metodo visualization
e una funzione che trasforma i valori in rappresentazioni di immagini RGB viene mappata alla raccolta NDVI.
Editor di codice (JavaScript)
// Filter MODIS NDVI image collection by a date range. var ndviCol = ee.ImageCollection('MODIS/061/MOD13A1') .filterDate('2018-01-01', '2019-01-01') .select('NDVI'); // Define visualization arguments. var visArgs = { min: 0, max: 9000, palette: [ 'FFFFFF', 'CE7E45', 'DF923D', 'F1B555', 'FCD163', '99B718', '74A901', '66A000', '529400', '3E8601', '207401', '056201', '004C00', '023B01', '012E01', '011D01', '011301' ] }; // Define a function to convert an image to an RGB visualization image and copy // properties from the original image to the RGB image. var visFun = function(img) { return img.visualize(visArgs).copyProperties(img, img.propertyNames()); }; // Map over the image collection to convert each image to an RGB visualization // using the previously defined visualization function. var ndviColVis = ndviCol.map(visFun);
Ecco un esempio di mappatura di una funzione di visualizzazione su una raccolta di immagini a più bande:
Editor di codice (JavaScript)
// Assemble a collection of Sentinel-2 surface reflectance images for a given // region and date range. var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-96.9037, 48.0395)) .filterDate('2019-06-01', '2019-10-01'); // Define visualization arguments. var visArgs = {bands: ['B11', 'B8', 'B3'], min: 300, max: 3500}; // Define a function to convert an image to an RGB visualization image and copy // properties from the original image to the RGB image. var visFun = function(img) { return img.visualize(visArgs).copyProperties(img, img.propertyNames()); }; // Map over the image collection to convert each image to an RGB visualization // using the previously defined visualization function. var s2colVis = s2col.map(visFun);
In questo caso, non viene fornito alcun argomento palette perché vengono fornite tre bande,
che definiscono l'intensità per ogni livello RGB. Tieni presente che entrambi gli esempi utilizzano i parametri min
e max
per controllare quali valori vengono estesi ai limiti dei dati RGB a 8 bit.
Miniatura del video
La funzione getVideoThumbURL()
genera un'animazione da tutte le immagini di un ImageCollection
in cui ogni immagine rappresenta un frame. Ecco il flusso di lavoro generale per la produzione di un'animazione:
- Definisci un
Geometry
i cui limiti determinano l'estensione regionale dell'animazione. - Definisci un
ImageCollection
. - Prendi in considerazione la visualizzazione delle immagini: mappa una funzione di visualizzazione delle immagini sulla raccolta o aggiungi gli argomenti di visualizzazione delle immagini all'insieme di argomenti di animazione.
- Definisci gli argomenti dell'animazione e chiama il metodo
getVideoThumbURL
.
Il risultato di getVideoThumbURL
è un URL. Stampa l'URL nella console e fai clic su di esso per avviare i server Earth Engine che generano l'animazione dinamicamente in una nuova scheda del browser. In alternativa, visualizza l'animazione nella console di Editor di codice chiamando la funzione ui.Thumbnail
sulla raccolta e sui relativi argomenti di animazione corrispondenti. Al termine del rendering, l'animazione è disponibile per il download facendo clic con il tasto destro del mouse e selezionando le opzioni appropriate dal menu contestuale.
L'esempio seguente illustra la generazione di un'animazione che mostra le temperature globali nel corso di 24 ore. Tieni presente che questo esempio include gli argomenti di visualizzazione insieme agli argomenti di animazione, anziché mappare prima una funzione di visualizzazione su ImageCollection
. Dopo aver eseguito questo script, nella console di Editor di codice dovrebbe apparire un'animazione simile a quella in Figura 3.
Editor di codice (JavaScript)
// Define an area of interest geometry with a global non-polar extent. var aoi = ee.Geometry.Polygon( [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null, false); // Import hourly predicted temperature image collection for northern winter // solstice. Note that predictions extend for 384 hours; limit the collection // to the first 24 hours. var tempCol = ee.ImageCollection('NOAA/GFS0P25') .filterDate('2018-12-22', '2018-12-23') .limit(24) .select('temperature_2m_above_ground'); // Define arguments for animation function parameters. var videoArgs = { dimensions: 768, region: aoi, framesPerSecond: 7, crs: 'EPSG:3857', min: -40.0, max: 35.0, palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'] }; // Print the animation to the console as a ui.Thumbnail using the above defined // arguments. Note that ui.Thumbnail produces an animation when the first input // is an ee.ImageCollection instead of an ee.Image. print(ui.Thumbnail(tempCol, videoArgs)); // Alternatively, print a URL that will produce the animation when accessed. print(tempCol.getVideoThumbURL(videoArgs));
Figura 3. Temperatura superficiale oraria per il solstizio d'inverno a nord rappresentata come immagine GIF animata.
Sequenza
La funzione getFilmstripThumbUrl
genera una singola immagine statica rappresentante la concatenazione di tutte le immagini in un ImageCollection
in una serie da nord a sud. La sequenza di fotogrammi della sequenza di immagini segue l'ordine naturale della raccolta.
Il risultato di getFilmstripThumbUrl
è un URL. Stampa l'URL nella console
e fai clic sull'URL per avviare i server Earth Engine che generano l'immagine al volo
in una nuova scheda del browser. Al termine del rendering, l'immagine è disponibile per il download facendo clic con il tasto destro del mouse e selezionando le opzioni appropriate dal menu contestuale.
Il seguente snippet di codice utilizza la stessa raccolta dell'esempio di miniatura del video riportato sopra. Dopo aver eseguito questo script, nella console di Code Editor dovrebbe apparire una sequenza simile a quella in Figura 4.
Editor di codice (JavaScript)
// Define an area of interest geometry with a global non-polar extent. var aoi = ee.Geometry.Polygon( [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null, false); // Import hourly predicted temperature image collection for northern winter // solstice. Note that predictions extend for 384 hours; limit the collection // to the first 24 hours. var tempCol = ee.ImageCollection('NOAA/GFS0P25') .filterDate('2018-12-22', '2018-12-23') .limit(24) .select('temperature_2m_above_ground'); // Define arguments for the getFilmstripThumbURL function parameters. var filmArgs = { dimensions: 128, region: aoi, crs: 'EPSG:3857', min: -40.0, max: 35.0, palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'] }; // Print a URL that will produce the filmstrip when accessed. print(tempCol.getFilmstripThumbURL(filmArgs));
Figura 4. Temperatura superficiale oraria per il solstizio d'inverno a nord rappresentata come immagine PNG in sequenza. Tieni presente che la sequenza di immagini è stata suddivisa in quattro sezioni per la visualizzazione. Il risultato di getFilmstripThumbURL
è un'unica serie di immagini della raccolta unite da nord a sud.
Tecniche avanzate
Le sezioni seguenti descrivono come utilizzare il ritaglio, l'opacità e la composizione di più livelli per migliorare le visualizzazioni aggiungendo bordi poligonali, mettendo in evidenza le regioni di interesse e confrontando le immagini all'interno di una raccolta.
Tieni presente che tutti gli esempi riportati di seguito in questa sezione utilizzano la stessa baseImageCollection
definita qui:
Editor di codice (JavaScript)
// Import hourly predicted temperature image collection for northern winter // solstice. Note that predictions extend for 384 hours; limit the collection // to the first 24 hours. var tempCol = ee.ImageCollection('NOAA/GFS0P25') .filterDate('2018-12-22', '2018-12-23') .limit(24) .select('temperature_2m_above_ground'); // Define visualization arguments to control the stretch and color gradient // of the data. var visArgs = { min: -40.0, max: 35.0, palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'] }; // Convert each image to an RGB visualization image by mapping the visualize // function over the image collection using the arguments defined previously. var tempColVis = tempCol.map(function(img) { return img.visualize(visArgs); }); // Import country features and filter to South American countries. var southAmCol = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017') .filterMetadata('wld_rgn', 'equals', 'South America'); // Define animation region (South America with buffer). var southAmAoi = ee.Geometry.Rectangle({ coords: [-103.6, -58.8, -18.4, 17.4], geodesic: false});
Sovrapposizioni
È possibile sovrapporre più immagini utilizzando il metodo blend
Image
, in cui i pixel sovrapposti di due immagini vengono fusi in base alle relative maschere (opacità).
Overlay vettoriale
L'aggiunta di poligoni di confine amministrativo e altre geometrie a un'immagine può fornire un contesto spaziale prezioso. Considera l'animazione della temperatura superficiale giornaliera mondiale sopra (Figura 3). I confini tra terra e oceano sono in qualche modo distinguibili, ma possono essere esplicitati aggiungendo un overlay a forma di poligono dei paesi.
I dati vettoriali (Features
) vengono disegnati nelle immagini applicando il metodo paint
.
Gli elementi possono essere dipinti su un'immagine esistente, ma la best practice è dipingerli su un'immagine vuota, applicare uno stile e poi fondere il risultato con altri livelli di immagine stilizzati. Il trattamento indipendente di ogni livello di una serie di visualizzazioni consente un maggiore controllo sullo stile.
L'esempio seguente mostra come dipingere i confini dei paesi sudamericani in un Image
vuoto e fondere il risultato con ogni Image
della raccolta delle temperature giornaliere globali (Figura 5). I confini dei paesi sovrapposti distinguono la terra dall'acqua e forniscono il contesto ai modelli di temperatura.
Editor di codice (JavaScript)
// Define an empty image to paint features to. var empty = ee.Image().byte(); // Paint country feature edges to the empty image. var southAmOutline = empty .paint({featureCollection: southAmCol, color: 1, width: 1}) // Convert to an RGB visualization image; set line color to black. .visualize({palette: '000000'}); // Map a blend operation over the temperature collection to overlay the country // border outline image on all collection images. var tempColOutline = tempColVis.map(function(img) { return img.blend(southAmOutline); }); // Define animation arguments. var videoArgs = { dimensions: 768, region: southAmAoi, framesPerSecond: 7, crs: 'EPSG:3857' }; // Display the animation. print(ui.Thumbnail(tempColOutline, videoArgs));
Figura 5. Aggiungi overlay vettoriali alle immagini di una raccolta per fornire un contesto spaziale.
Overlay immagine
È possibile sovrapporre più immagini per ottenere lo stile desiderato. Supponiamo di voler sottolineare una regione di interesse. Puoi creare una copia disattivata di una visualizzazione di immagini come livello di base e sovrapporre una versione ritagliata della visualizzazione originale. Basandosi sull'esempio precedente, lo script seguente produce la Figura 6.
Editor di codice (JavaScript)
// Define an empty image to paint features to. var empty = ee.Image().byte(); // Paint country feature edges to the empty image. var southAmOutline = empty .paint({featureCollection: southAmCol, color: 1, width: 1}) // Convert to an RGB visualization image; set line color to black. .visualize({palette: '000000'}); // Map a blend operation over the temperature collection to overlay the country // border outline image on all collection images. var tempColOutline = tempColVis.map(function(img) { return img.blend(southAmOutline); }); // Define a partially opaque grey RGB image to dull the underlying image when // blended as an overlay. var dullLayer = ee.Image.constant(175).visualize({ opacity: 0.6, min: 0, max: 255, forceRgbOutput: true}); // Map a two-part blending operation over the country outline temperature // collection for final styling. var finalVisCol = tempColOutline.map(function(img) { return img // Blend the dulling layer with the given country outline temperature image. .blend(dullLayer) // Blend a clipped copy of the country outline temperature image with the // dulled background image. .blend(img.clipToCollection(southAmCol)); }); // Define animation arguments. var videoArgs = { dimensions: 768, region: southAmAoi, framesPerSecond: 7, crs: 'EPSG:3857' }; // Display the animation. print(ui.Thumbnail(finalVisCol, videoArgs));
Figura 6. Metti in evidenza un'area di interesse ritagliando l'immagine e sovrapponendola a una copia disattivata.
Puoi anche combinare i dati delle immagini con un livello base con ombreggiatura delle colline per indicare il terreno e dare profondità alla visualizzazione (Figura 7).
Editor di codice (JavaScript)
// Define a hillshade layer from SRTM digital elevation model. var hillshade = ee.Terrain.hillshade(ee.Image('USGS/SRTMGL1_003') // Exaggerate the elevation to increase contrast in hillshade. .multiply(100)) // Clip the DEM by South American boundary to clean boundary between // land and ocean. .clipToCollection(southAmCol); // Map a blend operation over the temperature collection to overlay a partially // opaque temperature layer on the hillshade layer. var finalVisCol = tempColVis.map(function(img) { return hillshade .blend(img.clipToCollection(southAmCol).visualize({opacity: 0.6})); }); // Define animation arguments. var videoArgs = { dimensions: 768, region: southAmAoi, framesPerSecond: 7, crs: 'EPSG:3857' }; // Display the animation. print(ui.Thumbnail(finalVisCol, videoArgs));
Figura 7. Mostra il terreno sovrapponendo i dati delle immagini parzialmente trasparenti su un livello di ombreggiatura del rilievo.
Transizioni
Personalizza una raccolta di immagini per produrre animazioni che mostrano le differenze tra due immagini all'interno di una raccolta utilizzando transizioni di dissolvenza, sfarfallio e scorrimento. Ciascuno dei seguenti esempi utilizza la stessa visualizzazione di base generata dal seguente script:
Editor di codice (JavaScript)
// Define an area of interest geometry with a global non-polar extent. var aoi = ee.Geometry.Polygon( [[[-179.0, 78.0], [-179.0, -58.0], [179.0, -58.0], [179.0, 78.0]]], null, false); // Import hourly predicted temperature image collection. var temp = ee.ImageCollection('NOAA/GFS0P25') // Define a northern summer solstice temperature image. var summerSolTemp = temp .filterDate('2018-06-21', '2018-06-22') .filterMetadata('forecast_hours', 'equals', 12) .first() .select('temperature_2m_above_ground'); // Define a northern winter solstice temperature image. var winterSolTemp = temp .filterDate('2018-12-22', '2018-12-23') .filterMetadata('forecast_hours', 'equals', 12) .first() .select('temperature_2m_above_ground'); // Combine the solstice images into a collection. var tempCol = ee.ImageCollection([ summerSolTemp.set('season', 'summer'), winterSolTemp.set('season', 'winter') ]); // Import international boundaries feature collection. var countries = ee.FeatureCollection('USDOS/LSIB_SIMPLE/2017'); // Define visualization arguments. var visArgs = { min: -40.0, max: 35.0, palette: ['blue', 'purple', 'cyan', 'green', 'yellow', 'red'] }; // Convert the image data to RGB visualization images. // The clip and unmask combination sets ocean pixels to black. var tempColVis = tempCol.map(function(img) { return img .visualize(visArgs) .clipToCollection(countries) .unmask(0) .copyProperties(img, img.propertyNames()); });
Flicker
Con solo due immagini in una collezione, come in questo caso, il tremolio è la rappresentazione predefinita dell'animazione della collezione. Regola l'argomento
framesPerSecond
dell'animazione per aumentare o diminuire la frequenza
dell'intermittenza. I seguenti argomenti di visualizzazione applicati alla raccolta sopra riportata producono la Figura 8.
Editor di codice (JavaScript)
// Define arguments for animation function parameters. var videoArgs = { dimensions: 768, region: aoi, framesPerSecond: 2, crs: 'EPSG:3857' }; // Display animation to the Code Editor console. print(ui.Thumbnail(tempColVis, videoArgs));
Figura 8. Esempio di sfarfallio tra le 12:00 GMT e la temperatura della superficie per il solstizio d'inverno e a nord.
Dissolvenza
Una transizione di dissolvenza tra due livelli viene ottenuta diminuendo contemporaneamente l'opacità di un livello e aumentando quella dell'altro in una sequenza di incrementi di opacità da quasi 0 a 1 (Figura 9).
Editor di codice (JavaScript)
// Define a sequence of decreasing opacity increments. Note that opacity cannot // be 0, so near 1 and 0 are used. Near 1 is needed because a compliment is // calculated in a following step that can result in 0 if 1 is an element of the // list. var opacityList = ee.List.sequence({start: 0.99999, end: 0.00001, count: 20}); // Filter the summer and winter solstice images from the collection and set as // image objects. var summerImg = tempColVis.filter(ee.Filter.eq('season', 'summer')).first(); var winterImg = tempColVis.filter(ee.Filter.eq('season', 'winter')).first(); // Map over the list of opacity increments to iteratively adjust the opacity of // the two solstice images. Returns a list of images. var imgList = opacityList.map(function(opacity) { var opacityCompliment = ee.Number(1).subtract(ee.Number(opacity)); var winterImgFade = winterImg.visualize({opacity: opacity}); var summerImgFade = summerImg.visualize({opacity: opacityCompliment}); return summerImgFade.blend(winterImgFade).set('opacity', opacity); }); // Convert the image list to an image collection; the forward phase. var fadeForward = ee.ImageCollection.fromImages(imgList); // Make a copy of the collection that is sorted by ascending opacity to // represent the reverse phase. var fadeBackward = fadeForward.sort({property: 'opacity'}); // Merge the forward and reverse phase frame collections. var fadeCol = fadeForward.merge(fadeBackward); // Define animation arguments. var videoArgs = { dimensions: 768, region: aoi, framesPerSecond: 25, crs: 'EPSG:3857' }; // Display the animation. print(ui.Thumbnail(fadeCol, videoArgs));
Figura 9. Esempio di attenuazione tra le 12:00 GMT e la temperatura superficiale per il solstizio di estate e di inverno.
Dispositivo di scorrimento
Una transizione del cursore mostra e nasconde progressivamente il livello di immagine sottostante. Questo risultato viene ottenuto regolando in modo iterativo l'opacità dell'immagine sovrapposta su un intervallo di longitudini (Figura 10).
Editor di codice (JavaScript)
// Define a sequence of longitude increments. Start and end are defined by the // min and max longitude of the feature to be provided to the region parameter // of the animation arguments dictionary. var lonSeq = ee.List.sequence({start: -179, end: 179, count: 20}); // Define a longitude image. var longitude = ee.Image.pixelLonLat().select('longitude'); // Filter the summer and winter solstice images from the collection and set as // image objects. var summerImg = tempColVis.filter(ee.Filter.eq('season', 'summer')).first(); var winterImg = tempColVis.filter(ee.Filter.eq('season', 'winter')).first(); // Map over the list of longitude increments to iteratively adjust the mask // (opacity) of the overlying image layer. Returns a list of images. var imgList = lonSeq.map(function(lon) { lon = ee.Number(lon); var mask = longitude.gt(lon); return summerImg.blend(winterImg.updateMask(mask)).set('lon', lon); }); // Convert the image list to an image collection; concealing phase. var sliderColForward = ee.ImageCollection.fromImages(imgList); // Make a copy of the collection that is sorted by descending longitude to // represent the revealing phase. var sliderColbackward = sliderColForward .sort({property: 'lon', ascending: false}); // Merge the forward and backward phase frame collections. var sliderCol = sliderColForward.merge(sliderColbackward); // Define animation arguments. var videoArgs = { dimensions: 768, region: aoi, framesPerSecond: 25, crs: 'EPSG:3857' }; // Display the animation. print(ui.Thumbnail(sliderCol, videoArgs));
Figura 10. Esempio di transizione scorrevole tra la temperatura della superficie alle 12:00 GMT per il solstizio d'estate e d'inverno.