- Данни от Sentinel NDVI като примери

TL;DR

  • Добавете своя Shapefile към Assets
  • Използвайте JavaScript API на Google Earth Engine
  • Създайте индекс на нормализирана разлика в растителността (NDVI) от данни на Sentinel
  • Извлечете и визуализирайте времеви серии в конзолата за редактор на код на Earth Engine
  • Извличане и експортиране на големи времеви серии от данни в CSV

Когато работим с геопространствени данни, често се интересуваме от извличане на времеви редове за набор от местоположения. Това например могат да бъдат няколко точки или полигони, представляващи различни местоположения. В този кратък блог ще използваме JavaScript в редактора на код на Google Earth Engine и ще извлечем времеви серии върху набор от полигони. Ще използваме данни от Sentinel-2, за да извлечем индекса на нормализирана разлика в растителността (NDVI) за набор от напоявани полета. Нека започнем, като пренесем нашите данни за полигони в двигателя на Google Earth.

Добавяне на многоъгълен шейпфайл към активи

За да качите шейп файл като актив в Google Earth Engine, отидете до Assets в лявата странична лента, щракнете върху New и изберете Shapefiles от падащото меню. Ще се появи прозорец за качване на шейп файла, както е показано на екранната снимка по-долу.

Select файла от вашия компютър, който искате да качите, и щракнете върху качване. В този случай файлът се нарича mgck_shp.zip. Ще можете да видите напредъка на качването в Tasks страничната лента вдясно (вижте екранната снимка по-долу) и когато качването приключи, шейпфайлът ще се появи под CLOUD ASSETS в лявата странична лента (в този случай маркиран в жълто).

Импортирайте и визуализирайте FeatureCollection

Форматният файл, който току-що беше добавен към активите, може да бъде зареден и показан на картата, като се използва следната част от кода:

//Import GEE Feature Collection (field geometry) 
var geometry =ee.FeatureCollection("projects/ee-chinmaydeval91/assets/mgck_shp"); 

//Display polygons on a map 
Map.addLayer(geometry); Map.centerObject(geometry,14);

Това показва на картата осем напоявани селскостопански полета в Магическата долина, Айдахо.

Създайте и извлечете Sentinel NDVI

За разлика от композитните продукти MODIS NDVI, доколкото ми е известно, няма такъв предварително изчислен NDVI продукт за Sentinel на GEE. Така че първо ще трябва да създадем NDVI.

Импортиране на колекция от изображения

Нека започнем, като импортираме колекцията от изображения за повърхностно отражение на Sentinel-2, като напишем следния код:

// Import image collection of Sentinel-2 imagery, and 
// filter by start and end date, and 
// filter by boundary extent 

var S2 = ee.ImageCollection('COPERNICUS/S2') 
.filterDate('2019-03-28', '2021-12-31') 
.filterBounds(geometry);

Това импортира колекциите Sentinel-2 и ги филтрира за дадения период от време, както и границите на колекцията от функции. След това трябва да маскираме облачните и снежни изображения.

Маска Облаци и сняг

Попаднах на тази maskS2sr функция в UN Spider's Burn Severity mapping tutorial, която е написана за маскиране на облаци и сняг. Ще го използвам тук:

// Function to mask clouds from the pixel quality band of Sentinel-2 SR data. 

function maskS2sr(image) {
  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = ee.Number(2).pow(10).int();
  var cirrusBitMask = ee.Number(2).pow(11).int();
  // Get the pixel QA band.
  var qa = image.select('QA60');
  // All flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));
  // Return the masked image, scaled to TOA reflectance, without the QA bands.
  return image.updateMask(mask)
      .copyProperties(image, ["system:time_start"]);
}

// mask clouds and snow across the image collection
var S2 = S2.map(maskS2sr)

Сега имаме колекция от изображения Sentinel-2, която е без облаци и сняг и е филтрирана за дадените пространствени и времеви граници. Можем дори да изрежем колекцията от изображения към тези напоени полета.

Прикрепете към полигони на напоени полета

За да изрежем изображението по полигон, можем да използваме следната функция clipImgCollect и след това да я map в цялата колекция от изображения:

////// function to clip the entire ImageCollection to the field boundary //////
function clipImgCollect(img) {
  return img.clip(geometry);
}

// clip S2 ImageCollection to poly bounds
var clippedS2 = S2.map(clipImgCollect);

Изчислете NDVI

Сега към последната стъпка преди визуализацията — изчисляване на NDVI. Това може да се направи с помощта на функцията NDVI_from_S2 по-долу, която извършва математическите изчисления на лентата. След това можем да map тази функция към цялата колекция от изображения:

// Function to calculate and create NDVI
var NDVI_from_S2 = function(img) {
return img.addBands(img.normalizedDifference(['B8', 'B4']));
};

// map function across the S2 image collection and
// create NDVI
var clippedS2 = clippedS2.map(NDVI_from_S2);

Тази стъпка ще добави лента, наречена nd, съдържаща NDVI, към колекцията clippedS2.

Визуализирайте времеви серии

За да създадете диаграма на времеви редове, използвайте функционалността seriesByRegion и предайте статистиката, която трябва да се изчисли, към метода ee.Reducer, който помага за агрегирането на данни. В този случай ще агрегираме средните стойности на данните върху геометрията с помощта на функцията ee.Reducer.mean().

// Create a time series chart.
var plotNDVI_TS = ui.Chart.image.seriesByRegion(
  clippedS2, 
  geometry,ee.Reducer.mean(),
'nd',
500,
'system:time_start', 'system:index')
              .setChartType('LineChart')
              .setOptions({ // Plot customization options
      interpolateNulls: true,
      lineWidth: 1,
      pointSize: 2,
      title: 'Field mean NDVI',
      hAxis: {title: 'Date'},
      vAxis: {title: 'NDVI'}
});

print(plotNDVI_TS)

Това ще генерира графика на средната времева серия на полето NDVI за всички напоявани полета, както е показано по-долу. Тази диаграма може да бъде изтеглена такава, каквато е, или дори можете да изтеглите данните, изобразени в диаграмата като таблица (CSV).

Въпреки това, създаването на plotNDVI_TS, както е показано по-горе, със сигурност ще се провали, ако заявката ви за заявка надвишава 5000 елемента. Например в този пример току-що увеличих размера на моята колекция от изображения, като избрах много по-стара начална дата (2017-03-28) във функцията filterDate. Когато изпълних функцията plotNDVI_TS, получих грешка във вашата конзола, която изглежда така:

Данните, които се заявяват, са твърде големи, за да бъдат начертани в конзолата и трябва да бъдат експортирани от двигателя на Google Earth.

Експортиране на времеви редове в табличен формат

За да можете да експортирате големи времеви серии, първо изберете лентата NDVI от колекцията clippedS2 изображения. След това съпоставете функцията reduceRegions към тази колекция от NDVI изображения, за да изчислите средната стойност на NDVI за всяка характеристика (полигон на напоени полета) за всички изображения в колекцията. Също така ще съхраним датата на изображението в свойството date и ще го форматираме като ГГГГ-ММ-ДД. Този dat обект ще ни даде идентификатора на полигона, датата на изображението и средния NDVI за този полигон.

// Select ndvi band
var clippedS2_ndvi = clippedS2.select(['nd'])


// Collect image date and ndvi mean value for all features
var dat = clippedS2_ndvi.map(function(image) {
  return image.reduceRegions({
     collection:geometry ,
    reducer: ee.Reducer.mean().setOutputs(['ndvi']), 
    scale: 10
  }).filter(ee.Filter.neq('ndvi', null))
    .map(function(f) { 
      return f.set('date', image.date().format('YYYY-MM-dd'));
    });
}).flatten();

Сега, за да подготвите таблицата за експортиране, използвайте функцията format, показана по-долу, и я приложете към обект dat, за да я форматирате така, че всеки ред в таблицата да съдържа времева серия от средна стойност на NDVI за всеки многоъгълник на напоявано поле. Заглавията на колоните за всяка от тези стойности са датите на изображението, за които е изчислен средният NDVI. Форматираната таблица се съхранява в обекта sentinelNDVI_Results. Тази format функция е адаптирана от източника свързан тук.

var format = function(table, rowId, colId) {
  var rows = table.distinct(rowId); 
  var joined = ee.Join.saveAll('matches').apply({
    primary: rows, 
    secondary: table, 
    condition: ee.Filter.equals({
      leftField: rowId, 
      rightField: rowId
    })
  });
  return joined.map(function(row) {
      var values = ee.List(row.get('matches'))
        .map(function(feature) {
          feature = ee.Feature(feature);
          var ndvi_val = ee.List([feature.get('ndvi'), -9999]).reduce(ee.Reducer.firstNonNull());
          return [feature.get(colId), ee.Number(ndvi_val).format("%.3f")];
        });
      return row.select([rowId]).set(ee.Dictionary(values.flatten()));
    });
};

// Apply format function to the dat object
var sentinelNDVI_Results = format(dat, 'ID', 'date');

Експортирането на тази форматирана таблица в Google Drive е доста лесно. Просто предайте обекта sentinelNDVI_Results на функцията Export.table.toDrive. Други аргументи, които трябва да посочите, включват folder на устройството, където искате да експортирате файла, fileNamePrefix - префикс, който да се използва в името на файла, и fileFormat:

// Export data frame to Google Drive as a CSV
Export.table.toDrive({
  collection: sentinelNDVI_Results,
  description: 'Sentinel_NDVI_TS',
  folder: 'earthengine',
  fileNamePrefix: 'sentinel_ndvi_ts_demo_',
  fileFormat: 'CSV'
})

Ето един кратък поглед в експортираните времеви серии, които бързо начертах в Excel за демонстрация:

Можете да намерите пълния код, използван в този блог на тази GEE връзка.

Първоначално публикувано на https://chinmaydeval.com.