אפשר להציג את התמונות שמרכיבות את ה-ImageCollection
כאנימציה או כסדרה של תמונות ממוזערות שנקראות 'סרטון'. השיטות האלה מאפשרות להעריך במהירות את התוכן של ה-ImageCollection
, והן אמצעי יעיל להצגת שינויים במרחב ובזמן (איור 1).
getVideoThumbURL()
יוצר סדרה של תמונות מונפשותgetFilmstripThumbURL()
יוצר סדרה של תמונות ממוזערות
בקטעים הבאים מוסבר איך להכין ImageCollection
להצגה חזותית, מוצג קוד לדוגמה לכל שיטה להצגה חזותית של אוסף, ומפורטות כמה שיטות מתקדמות ליצירת אנימציה.
איור 1. אנימציה שמראה את התקדמות ההוריקנים באוקיינוס האטלנטי במשך שלושה ימים בספטמבר 2017.
הכנת האוסף
אפשר לסנן, ליצור קומפוזיציות, למיין ולסגנן תמונות בתוך אוסף כדי להציג רק את התמונות שמעניינות אתכם או כדי להדגיש תופעה מסוימת. אפשר לספק כל ImageCollection
כקלט לפונקציות התצוגה החזותית, אבל אוסף שנבחר בקפידה תוך התחשבות בטווחי תאריכים שנתיים ותוך-שנתיים, במרווחי התצפית, בהיקף האזורי, באיכות ובתצוגה יכול להניב תוצאות טובות יותר.
סינון
סינון אוסף תמונות כך שיכלול רק נתונים רלוונטיים שתומכים במטרה של הוויזואליזציה. כדאי להביא בחשבון תאריכים, היקף גיאוגרפי, איכות ומאפיינים אחרים שספציפיים למערך נתונים נתון.
לדוגמה, אפשר לסנן אוסף של השתקפות פני השטח של Sentinel-2 לפי:
טווח תאריכים אחד,
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterDate('2018-01-01', '2019-01-01');
טווח רצוף של ימים בשנה,
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filter(ee.Filter.calendarRange(171, 242, 'day_of_year'));
אזור עניין,
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2));
או נכס תמונה.
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 50));
לשרשר כמה מסננים.
Code Editor (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');
עיבוד (compositing)
טווחי תאריכים מורכבים בתוך שנה ובין שנים כדי לצמצם את מספר התמונות באוסף ולשפר את האיכות. לדוגמה, נניח שאתם רוצים ליצור תצוגה חזותית של מדד NDVI שנתי לאפריקה. אפשרות אחת היא פשוט לסנן אוסף NDVI של 16 ימים מ-MODIS כך שיכלול את כל התצפיות מ-2018.
Code Editor (JavaScript)
var ndviCol = ee.ImageCollection('MODIS/006/MOD13A2') .filterDate('2018-01-01', '2019-01-01') .select('NDVI');
קומפוזיציה בין-שנתית לפי מסנן וצמצום
בתצוגה החזותית של האוסף שלמעלה מוצגת רמת רעש גבוהה באזורים המיוערים שבהם יש כיסוי עננים כבד (איור 2א). כדי לקבל ייצוג טוב יותר, אפשר לצמצם את טווחי התאריכים של הרצף לפי חציון בכל השנים באוסף MODIS.
Code Editor (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);
האנימציה שנוצרת מהאוסף הזה מכילה פחות רעשי רקע, כי כל תמונה מייצגת את החציון של תמונת NDVI משולבת של 16 ימים, על סמך נתונים שנצברו במשך יותר מ-20 שנה (איור 1ב). מידע נוסף על האנימציה הזו זמין במדריך הזה.
איור 2א. מדד NDVI שנתי ללא שילוב בין שנים. | איור 2ב. מדד NDVI שנתי עם קומפוזיציה בין-שנתית. |
נתונים משולבים בתוך השנה לפי מסנן וצמצום
בדוגמה הקודמת נעשה שימוש בשילוב בין שנים. כדאי גם ליצור סדרה של תצפיות במהלך השנה. לדוגמה, נתוני Landsat נאספים כל שש עשרה ימים עבור סצנה מסוימת לכל חיישן, אבל לרוב חלק מהתמונות מטושטשות בגלל עננים. אפשר להסתיר את העננים ולערוך כמה תמונות מאותו עונה כדי ליצור תמונה נקייה יותר. בדוגמה הבאה, תמונות Landsat 5 מחודשי יולי ואוגוסט מורכבות באמצעות החציון של כל שנה מ-1985 עד 2011.
Code Editor (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);
נתונים משולבים בתוך השנה על ידי צירוף ופחתה
שימו לב ששתי שיטות הקומפוזיציה הקודמות ממפות List
ימים ושנים כדי להגדיר באופן מצטבר תאריכים חדשים לסינון ולקומפוזיציה.
שימוש בחיבור (join) הוא שיטה נוספת לביצוע הפעולה הזו. בקטע הקוד הבא מוגדר אוסף ייחודי של שנים, ולאחר מכן מחילים צירוף saveAll
כדי לזהות את כל התמונות שתואמות לשנה מסוימת.
תמונות ששייכות לשנה מסוימת מקובצות באובייקט List
, שמאוחסן כנכס של הנציג של השנה הרלוונטית באוסף השנים הייחודי. כדי ליצור נתונים משולבים שנתיים מהרשימות האלה, מפחיתים את הערך של ImageCollections
שהן מגדירות בפונקציה שממופת על פני האוסף של השנים הנפרדות.
Code Editor (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);
יצירת תרשים מורכב באותו יום באמצעות צירוף ופחתה
שימוש נוסף ב-Compositing הוא ליצירת פסיפס של תמונות שתוחמות זו את זו מבחינה מרחבית. נניח שאזור העניין שלכם משתרע על פני שתי שורות של Landsat באותו נתיב, והמטרה שלכם היא להציג מוזיקת תמונות של שתי התמונות לכל מסלול של Landsat 8 בשנים 2017 ו-2018. כאן, אחרי סינון האוסף לפי נתיב ושורה, נעשה שימוש בפעולה של צירוף (join) כדי ליצור פסיפס של תמונות Landsat מאותו אובייקט, שמוגדר לפי תאריך הרכישה.
Code Editor (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(); }));
מיון
אפשר למיין את האוסף לפי זמן כדי לוודא את הסדר הכרונולוגי הנכון, או לפי מאפיין לבחירתכם. כברירת מחדל, סדרת הפריים של התצוגה החזותית ממוינת לפי הסדר הטבעי של האוסף. אפשר לשנות את הסדר של הסדרה באמצעות שיטת האוסף sort
, שבה נכס Image
נבחר למיון בסדר עולה או יורד. לדוגמה, כדי למיין לפי זמן התצפית, משתמשים במאפיין system:time_start
הנפוץ.
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2)) .sort('system:time_start');
לחלופין, אפשר להגדיר את הסדר לפי רמת עננות גוברת, כמו במקרה הזה של תמונות Sentinel-2.
Code Editor (JavaScript)
var s2col = ee.ImageCollection('COPERNICUS/S2_SR') .filterBounds(ee.Geometry.Point(-122.1, 37.2)) .sort('CLOUDY_PIXEL_PERCENTAGE');
אפשר גם להגדיר את הסדר לפי מאפיין נגזר, כמו NDVI אזורית ממוצעת. כאן, מדד NDVI אזורי מתווסף כנכס לכל תמונה בפונקציה ממופה, ולאחר מכן מתבצעת מיון לפי הנכס החדש.
Code Editor (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);
הצגה חזותית של תמונות
בתצוגה החזותית של תמונות, מספרים הופכים לצבעים. יש שלוש דרכים לקבוע איך נתוני התמונות יוצגו כצבע בשיטות להצגה חזותית של אוספים:
- מעבירים את הארגומנטים של התצוגה החזותית ישירות ל-
getVideoThumbURL
ול-getFilmstripThumbURL
. - ממפים את שיטת התמונה
visualize
על אוסף התמונות לפני החלתgetVideoThumbURL
ו-getFilmstripThumbURL
. - ממפים את שיטת התמונה
sldStyle
על אוסף התמונות לפני החלתgetVideoThumbURL
ו-getFilmstripThumbURL
. מידע נוסף זמין במאמר Styled Layer Descriptor.
בדוגמאות במדריך הזה נעשה שימוש באפשרויות 1 ו-2, שבהן התצוגה החזותית מתקבלת על ידי מיפוי של שלושה פסים של תמונה בתמונה עם כמה פסים לערוצי צבע אדום, ירוק וכחול, או על ידי שיוך ערכים של פס אחד באופן לינארי על פני לוח צבעים. הפרמטרים של התצוגה החזותית כוללים:
פרמטר | תיאור | סוג |
---|---|---|
bands | רשימה מופרדת בפסיקים של שלושה שמות של פסות שרוצים למפות ל-RGB | list |
min | הערכים שרוצים למפות ל-0 | מספר או רשימה של שלושה מספרים, אחד לכל תחום |
max | הערכים למיפוי לערך 255 | מספר או רשימה של שלושה מספרים, אחד לכל תחום |
gain | הערכים שבהם צריך להכפיל כל ערך פיקסל | מספר או רשימה של שלושה מספרים, אחד לכל תחום |
bias | הערכים שצריך להוסיף לכל DN | מספר או רשימה של שלושה מספרים, אחד לכל תחום |
gamma | גורמי תיקון גאמה | מספר או רשימה של שלושה מספרים, אחד לכל תחום |
palette | רשימה של מחרוזות צבעים בסגנון CSS (תמונות עם פס אחד בלבד) | רשימה של מחרוזות הקסדצימליות מופרדות בפסיקים |
opacity | השקיפות של השכבה (0.0 היא שקיפות מלאה ו-1.0 היא אטימות מלאה) | number |
משתמשים בארגומנט bands
כדי לבחור את הלהקות שרוצים להציג. יש לספק רשימה של שם אחד או שלושה שמות של להקות. לגבי תמונות עם כמה תדרים, כברירת מחדל נבחרים שלושת התדרים הראשונים. סדר השמות של הלהקות קובע את הקצאת הצבעים. הלהקות הראשונה, השנייה והשלישית ברשימה ממופות לצבע אדום, ירוק וכחול, בהתאמה.
שינוי קנה המידה של טווח הנתונים הוא שיקול חשוב כשמציגים תמונות באופן חזותי. כברירת מחדל, ערכים של נתונים בנקודה צפה בין 0 ל-1 (כולל) מותאמים לערך בין 0 ל-255 (כולל). ערכים מחוץ לטווח הזה מוגדרים באופן אוטומטי ל-0 ול-255, בהתאם לכך שהם קטנים מ-0 או גדולים מ-1, בהתאמה. לגבי נתוני מספר שלם, הקיבולת המלאה שמוגדרת לפי הסוג שלו מותאמת לטווח שבין 0 ל-255 (לדוגמה, לנתונים בעלי 16 ביט עם סימן יש טווח של -32,768 עד 32,767, שמתאימים לטווח [0, 255] כברירת מחדל). לרוב, אישור ההגדרות שמוגדרות כברירת מחדל יכול להוביל ליצירת תצוגות חזותיות עם קונטראסט נמוך או ללא קונטראסט בכלל בין תכונות התמונה. משתמשים ב-min
וב-max
כדי לשפר את הניגודיות ולהדגיש טווח נתונים מסוים. ככלל, מומלץ להגדיר את min
ו-max
לערכים שמייצגים את האחוזון השני ואת האחוזון ה-98 של הנתונים באזור העניין. בדוגמה הבאה מוסבר איך מחשבים את הערכים האלה במודל גובה דיגיטלי.
Code Editor (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());
הפרמטר palette
מגדיר את הצבעים שמייצגים את תמונת התצוגה החזותית של 8 סיביות. הוא רלוונטי רק לייצוגים של תדר יחיד. אם מציינים אותו בתמונה עם כמה תדרים, מתקבלת שגיאה.
אם הנתונים הם של תדר יחיד או אם רוצים להציג חזותית תדר יחיד מתמונה עם כמה תדרים, מגדירים את הפרמטר forceRgbOutput
כ-true
(לא צריך לעשות זאת אם מציינים את הארגומנט palette
). משתמשים בפרמטר min
ובפרמטר max
כדי להגדיר את טווח הערכים שרוצים לשנות באופן לינארי בין 0 ל-255.
בהמשך מופיעה דוגמה למיפוי של פונקציית ויזואליזציה על אוסף תמונות של תדר יחיד. מתבצע ייבוא של אוסף NDVI של MODIS, מגדירים את הארגומנטים של התצוגה החזותית של השיטה visualization
וממפים פונקציה שממירה ערכים לייצוגים של תמונות RGB על האוסף של NDVI.
Code Editor (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);
דוגמה למיפוי של פונקציית ויזואליזציה על אוסף תמונות עם כמה תדרים:
Code Editor (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);
במקרה כזה, לא מציינים ארגומנט של צבעים כי נותנים שלושה פסים שמגדירים את העוצמה של כל שכבת RGB. שימו לב שבשתי הדוגמאות נעשה שימוש בפרמטרים min
ו-max
כדי לקבוע אילו ערכים יימתחו עד למגבלות של נתוני ה-RGB ב-8 ביט.
תמונה ממוזערת של סרטון
הפונקציה getVideoThumbURL()
יוצרת אנימציה מכל התמונות ב-ImageCollection
, כאשר כל תמונה מייצגת פריים. תהליך העבודה הכללי ליצירת אנימציה הוא:
- מגדירים את
Geometry
, שהגבולות שלו קובעים את ההיקף האזורי של האנימציה. - מגדירים
ImageCollection
. - כדאי לשקול להשתמש בתצוגה חזותית של תמונות: אפשר למפות פונקציה של תצוגה חזותית של תמונות על האוסף או להוסיף ארגומנטים של תצוגה חזותית של תמונות לקבוצת הארגומנטים של האנימציה.
- מגדירים את הארגומנטים של האנימציה ומפעילים את השיטה
getVideoThumbURL
.
התוצאה של getVideoThumbURL
היא כתובת URL. מדפיסים את כתובת ה-URL במסוף ולוחצים עליה כדי להפעיל את שרתי Earth Engine שייצרו את האנימציה בזמן אמת בכרטיסייה חדשה בדפדפן. לחלופין, אפשר להציג את האנימציה במסוף של Code Editor על ידי קריאה לפונקציה ui.Thumbnail
על האוסף ועל ארגומנטים האנימציה התואמים שלו. לאחר היצירה, האנימציה תהיה זמינה להורדה. כדי להוריד אותה, לוחצים לחיצה ימנית עליה ובוחרים באפשרויות המתאימות בתפריט ההקשר.
בדוגמה הבאה מוסבר איך ליצור אנימציה שמציגה את הטמפרטורות ברחבי העולם במשך 24 שעות. שימו לב שהדוגמה הזו כוללת ארגומנטים של תצוגה חזותית יחד עם ארגומנטים של אנימציה, בניגוד למיפוי קודם של פונקציית תצוגה חזותית על ImageCollection
. כשמריצים את הסקריפט, אמורה להופיע אנימציה שדומה לזו שמוצגת באיור 3 במסוף של Code Editor.
Code Editor (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));
איור 3. טמפרטורת פני השטח השעתית של היפוך עונת החורף בצפון, שמוצגת כקובץ GIF מונפש.
רצועת תמונות
הפונקציה getFilmstripThumbUrl
יוצרת תמונה סטטית אחת שמייצגת את שרשור כל התמונות ב-ImageCollection
לסדרה מצפון לדרום. רצף התמונות בסרטון הווידאו עוקב אחרי הסדר הטבעי של האוסף.
התוצאה של getFilmstripThumbUrl
היא כתובת URL. מדפיסים את כתובת ה-URL במסוף ולוחצים עליה כדי להתחיל את יצירת התמונה על-ידי שרתי Earth Engine בזמן אמת בכרטיסייה חדשה בדפדפן. לאחר העיבוד, אפשר להוריד את התמונה בלחיצה ימנית עליה ובחירה באפשרויות המתאימות בתפריט ההקשר.
קטע הקוד הבא משתמש באותה אוסף כמו בדוגמה של התמונה הממוזערת של הסרטון שלמעלה. כשמריצים את הסקריפט הזה, אמורה להופיע בחלונית של Code Editor פסלה דומה לזו שמוצגת באיור 4.
Code Editor (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));
איור 4. הטמפרטורה השעתית של פני השטח ביום ההיפוך החורפי של חצי הכדור הצפוני, מיוצגת כתמונה בפורמט PNG של סרט צילום. שימו לב שפס ההדמיה חולק לארבעה קטעים לצורך הצגה. התוצאה של getFilmstripThumbURL
היא סדרה אחת של תמונות מהאוסף שמחוברות מצפון לדרום.
טכניקות מתקדמות
בקטעים הבאים מוסבר איך להשתמש בקציצת תמונות, בשקיפות ובשילוב שכבות כדי לשפר את התצוגות החזותיות על ידי הוספת גבולות פוליגונים, הדגשת אזורים של עניין והשוואה בין תמונות בתוך אוסף.
שימו לב: בכל הדוגמאות הבאות בקטע הזה נעשה שימוש באותה פונקציית בסיס ImageCollection
שמוגדרת כאן:
Code Editor (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});
שכבות-על
אפשר להוסיף שכבות של כמה תמונות באמצעות השיטה blend
Image
, שבה פיקסלים חופפים משתי תמונות מעורבבים על סמך המסכות שלהם (העמעום).
שכבת-על של וקטור
הוספת פוליגונים של גבולות מנהליים וגיאומטריות אחרות לתמונה יכולה לספק הקשר מרחבי חשוב. אפשר להיעזר בהנפשה של טמפרטורת פני השטח הגלובלית היומית שלמעלה (איור 3). אפשר להבחין במידה מסוימת בין היבשה לאוקיינוס, אבל אפשר להדגיש את ההבדל באמצעות שכבת-על של פוליגונים של מדינות.
נתונים וקטורים (Features
) מצוירים בתמונות באמצעות החלת השיטה paint
.
אפשר לצייר תכונות בתמונה קיימת, אבל מומלץ יותר לצייר אותן בתמונה ריקה, להוסיף לה סגנון ואז למזג את התוצאה עם שכבות אחרות של תמונות עם סגנון. טיפול בכל שכבה של מקבץ התצוגות החזותית בנפרד מאפשר יותר שליטה בסגנון.
בדוגמה הבאה מוצגת צביעה של גבולות המדינות בדרום אמריקה ב-Image
ריק, והמיזוג של התוצאה עם כל Image
של אוסף הטמפרטורות היומיות הגלובלי (איור 5). גבולות המדינות שמופיעים בשכבה העליונה מאפשרים להבדיל בין יבשה למים ומספקים הקשר לדפוסי הטמפרטורה.
Code Editor (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));
איור 5. מוסיפים שכבות-על וקווים וקטוריים לתמונות באוסף כדי לספק הקשר מרחבי.
שכבת-על לתמונה
אפשר להוסיף כמה שכבות של תמונות כדי ליצור את הסגנון הרצוי. נניח שאתם רוצים להדגיש אזור עניין. אפשר ליצור עותק מושתק של התצוגה החזותית של התמונה כשכבת בסיס, ואז להוסיף שכבת-על של גרסה חתוכה של התצוגה החזותית המקורית. בהמשך לדוגמה הקודמת, הסקריפט הבא יוצר את תרשים 6.
Code Editor (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));
איור 6. כדי להדגיש אזור עניין, אפשר לחתוך את התמונה ולהוסיף אותה כשכבת-על על עותק מושתק.
אפשר גם למזג נתוני תמונה עם שכבת בסיס של צללי גבעות כדי לציין את פני השטח ולהוסיף עומק להדמיה (איור 7).
Code Editor (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));
איור 7. כדי להציג את פני השטח, אפשר להוסיף שכבת-על של נתוני תמונה שקופים חלקית לשכבת הצללה.
מעברים.
אפשר להתאים אישית אוסף תמונות כדי ליצור אנימציות שמציגות את ההבדלים בין שתי תמונות באותו אוסף באמצעות מעברים של דהייה, הבהוב ותנועה. בכל אחת מהדוגמאות הבאות נעשה שימוש באותה תצוגה חזותית בסיסית שנוצרה באמצעות הסקריפט הבא:
Code Editor (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
אם יש רק שתי תמונות באוסף, כמו במקרה הזה, הבהוב הוא ייצוג ברירת המחדל באנימציה של האוסף. משנים את הארגומנט של האנימציה framesPerSecond
כדי להאיץ או להאט את קצב הפליקרים. הארגומנטים הבאים להצגה חזותית, שהוחלו על האוסף שלמעלה, יוצרים את איור 8.
Code Editor (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));
איור 8. דוגמה לתנודות בטמפרטורת פני השטח בשעה 12:00 (שעון גריניץ') באירופה הצפונית ובחורף.
עמעום
כדי ליצור מעבר הדרגתי בין שתי שכבות, מפחיתים בו-זמנית את האטימות של שכבה אחת ומגדילים את האטימות של השנייה ברצף של הגדלות אטימות מ-0 ל-1 (איור 9).
Code Editor (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));
איור 9. דוגמה להחלפה בין טמפרטורת פני השטח בשעה 12:00 (שעון גריניץ') בקיץ ובחורף.
מחוון
טרנזישן של פס הזזה מציג ומסתיר בהדרגה את שכבת התמונה הבסיסית. כדי לעשות זאת, משנים באופן איטרטיבי את השקיפות של התמונה העליונה במגוון קוי אורך (איור 10).
Code Editor (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));
איור 10. דוגמה למעבר חלק בין טמפרטורת פני השטח בשעה 12:00 (שעון גריניץ') בקיץ ובחורף.