Google Earth Engine: как сопоставить функцию с набором всех датчиков Landsat для создания временных рядов NDVI

Я пытаюсь объединить все датчики Landsat (L4-l8) с 1980-х годов для представления в Google Earth Engine и вычислить временные ряды индекса NDVI (после удаления облаков)

Я попытался найти способ решить проблему, заключающуюся в том, что L8 использует разные диапазоны для NIR и RED, чем L4-L7, путем добавления кода из другого Q & A ( Google Earth Engine: маскируйте облака и отображайте функцию на коллекции изображений с различных датчиков )

Я получаю коллекцию изображений, содержащую все наборы данных Landsat с одним бэндом NDVI. Однако, когда я затем добавляю код для создания диаграммы временных рядов, я получаю следующую ошибку:

'Ошибка создания диаграммы: никакие функции не содержат ненулевых значений "system: time_start"'

Мне интересно, связано ли это с тем, что сбор производится из разных наборов данных датчиков, но я не знаю, как это решить.

Кто-нибудь может мне помочь?

Спасибо.

Ниже приведен код [ОТРЕДАКТИРОВАН, чтобы сделать код воспроизводимым]:

//Define a region of interest - Baringo county, kenya
var Baringo2 = /* color: #98ff00 */ee.Geometry.Polygon(
        [[[35.69382363692023, 1.4034169899773616],
          [35.69382363692023, 1.2606333558875118],
          [35.61691934004523, 1.0079975313237526],
          [35.58945351973273, 0.6509798625215468],
          [35.71030312910773, 0.35436075019447294],
          [35.72128945723273, 0.18956774160826206],
          [35.61691934004523, 0.18407460674896256],
          [35.58945351973273, 0.13463632293582842],
          [35.71030312910773, 0.04125265421470341],
          [35.68283730879523, -0.0466379620709295],
          [35.74875527754523, -0.18945988757796725],
          [35.96848184004523, 0.05223897866641199],
          [36.09482461348273, 0.002800509340276178],
          [36.27060586348273, 0.2719645271288622],
          [36.23215371504523, 0.45872822561768967],
          [36.32004434004523, 0.6509798625215468],
          [36.47934609785773, 0.8651943843139164],
          [36.32004434004523, 0.9915205478901427],
          [36.18271523848273, 1.1672705367627716],
          [36.08933144942023, 1.1892385469740003],
          [35.79270059004523, 1.6944479915417494]]]);

//print (Baringo2);


//define land cover categories and sample points:

//DEG, 'Open Access Grazing'
var DEG2 = /* color: #d63000 */ee.Geometry.MultiPoint(
        [[35.981082916259766, 0.44974818893112445],
         [35.98460465669632, 0.4510302452289453],
         [35.987091064453125, 0.451808061701256],
         [35.98616033792496, 0.4483427545719104],
         [35.987573862075806, 0.4297931417762091],
         [35.9996223449707, 0.45043481325254864],
         [36.06963872909546, 0.3470539601321629],
         [36.06938123703003, 0.3475260202469071],
         [36.069630682468414, 0.34738386578302555],
         [36.070003509521484, 0.3475903920789125],
         [36.06644153594971, 0.35022933035465353],
         [36.05863630771637, 0.3589468796649346],
         [36.05862021446228, 0.3589039651627689],
         [35.98088979721069, 0.4486537280584078],
         [36.07082426548004, 0.37428880110513496],
         [36.07011079788208, 0.3772229960862265],
         [36.032023429870605, 0.627012774441952],
         [36.03208780288696, 0.6266319235542508],
         [36.03143334388733, 0.6271683332472826],
         [35.98740756511688, 0.4303348413873794],
         [35.997237861156464, 0.44501955275654603]]);

//GM, 'Managed Grazing'
var GM2 = /* color: #8b1062 */ee.Geometry.MultiPoint(
        [[36.030564308166504, 0.6268519274914895],
         [36.03069305419922, 0.6269592094299815],
         [36.03039264678955, 0.6268948402671484],
         [36.03148698806763, 0.6315292660507418],
         [36.03124022483826, 0.6309284876929263],
         [36.03038191795349, 0.630005863651221],
         [36.03060722351074, 0.6335886212975799],
         [35.99500894513767, 0.5747552592254358],
         [36.02037191456475, 0.5758710045457109],
         [36.01653099125542, 0.5782526853495346],
         [36.017239094435354, 0.5785959906083284],
         [36.017346383450786, 0.5729096907628695],
         [36.015372277615825, 0.5705065511240786],
         [36.04236602652236, 0.5423771737070896],
         [36.040499209047994, 0.539373233463203],
         [36.04056358337402, 0.38151398068151043],
         [36.03893280029297, 0.3785528870665109]]);

//REF, Nature Conservancy
var REF2 = /* color: #98ff00 */ee.Geometry.MultiPoint(
        [[36.094207763671875, 0.22436084629270164],
         [36.0926628112793, 0.2264207668774221],
         [36.090946197509766, 0.23088392713673156],
         [36.089229583740234, 0.23672036535773863],
         [36.09781265258789, 0.6451750427539986],
         [36.096739768981934, 0.6450033922571318],
         [36.097726821899414, 0.6443597028423275],
         [36.09734058380127, 0.6434156248868509],
         [36.0975980758667, 0.642686109983424],
         [36.123390197753906, 0.6421282455751846],
         [36.124634742736816, 0.6414845557977334]]);

//CRO, 'Crops'
var CRO2 = /* color: #5980ff */ee.Geometry.MultiPoint(
        [[36.044254302978516, 0.5421843671379806],
         [36.04090690481826, 0.47892844903645376],
         [36.041936873079976, 0.4832198321871975],
         [36.03189468252822, 0.48802617809656],
         [36.02786064016982, 0.4869962471182337],
         [36.02193832266494, 0.4859663159825207],
         [36.014471052767476, 0.47772686127176456],
         [36.02193832266494, 0.47437957996379887],
         [36.018505095125875, 0.4748087186837464],
         [36.00992202627822, 0.47746937815196017],
         [36.00906371939345, 0.4767827564520509],
         [36.00382804739638, 0.47626779013219045],
         [36.003398893954, 0.4747228909418917],
         [36.010007856966695, 0.4700881913046016],
         [36.014471052767476, 0.47128978039605285],
         [36.01962089407607, 0.4713756081803616],
         [36.02485656607314, 0.47970089820257816],
         [36.02511405813857, 0.4857088331740545],
         [36.04159355032607, 0.4773835504432214],
         [36.032752989412984, 0.47377878571117404],
         [36.00447177886963, 0.42708894038807443],
         [36.002798080444336, 0.4288055062751536],
         [36.00245475769043, 0.42777556678899614],
         [36.00425720214844, 0.4239562066570169],
         [36.00627422332764, 0.42588734403892814],
         [36.00099563598633, 0.4293204759663003],
         [36.00425720214844, 0.4286767638469664],
         [36.00425720214844, 0.4327965204722641],
         [36.008548736572266, 0.4323244651387205],
         [36.01219654083252, 0.42425660583700076]]);


//mask clouds for L8, and then L5-7

// Function to cloud mask Landsat 8.
var maskL8SR = function(image) {
  // Bits 3 and 5 are cloud shadow and cloud, respectively.
  var cloudShadowBitMask = ee.Number(2).pow(3).int();
  var cloudsBitMask = ee.Number(2).pow(5).int();
  // Get the QA band.
  var qa = image.select('pixel_qa');
  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0).and(
            qa.bitwiseAnd(cloudsBitMask).eq(0));
  return image
      // Scale the data to reflectance and temperature.
      .select(['B4', 'B5'], ['Red', 'NIR']).multiply(0.0001)
      .updateMask(mask);
};

// Function to cloud mask Landsats 4-7
var maskL57SR = function(image) {
  var qa = image.select('pixel_qa');
  // Second bit must be zero, meaning none to low cloud confidence.
  var mask1 = qa.bitwiseAnd(ee.Number(2).pow(7).int()).eq(0).and(
      qa.bitwiseAnd(ee.Number(2).pow(3).int()).lte(0)); // cloud shadow
  // This gets rid of noise at the edge of the images.
  var mask2 = image.select('B.*').gt(0).reduce('min');
  return image
      .select(['B3', 'B4'], ['Red', 'NIR']).multiply(0.0001)
      .updateMask(mask1.and(mask2));
};

//NDVI functions

//NDVI functions for l8
var addNDVI_l8 = function(image) {
  var ndvi = image.normalizedDifference(['NIR', 'Red']).rename('NDVI');
  return image.addBands(ndvi);
};

//NDVI functions for l4-7
var addNDVI_l457 = function(image) {
  var ndvi = image.normalizedDifference(['NIR', 'Red']).rename('NDVI');
  return image.addBands(ndvi);
};


// find all data and filter them by date and add NDVI
var lst5 = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR')
    .filterDate('1984-10-01', '2011-10-01')
    .filterBounds(Baringo2)  // filter to area-of-interest; 
    .map(maskL57SR)
    .map(addNDVI_l457).select('NDVI');


var lst7 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
    .filterDate('2011-10-01', '2013-04-07')
    .filterBounds(Baringo2)  // filter to area-of-interest;
    .map(maskL57SR)
    .map(addNDVI_l457).select('NDVI');


var lst8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
    .filterDate('2013-04-07', '2018-05-01')
    .filterBounds(Baringo2)  // filter to area-of-interest;
    .map(maskL8SR)
    .map(addNDVI_l8).select('NDVI');


var lst7_08 = ee.ImageCollection('LANDSAT/LE07/C01/T1_SR')
    .filterDate('2007-12-01', '2008-02-01')
    .filterBounds(Baringo2)  // filter to area-of-interest;
    .map(maskL57SR)
    .map(addNDVI_l457).select('NDVI');



var lst7_92 = ee.ImageCollection('LANDSAT/LT04/C01/T1_SR')
    .filterDate('1992-01-02', '1992-04-01')
    .filterBounds(Baringo2)  // filter to area-of-interest;
    .map(maskL57SR)
    .map(addNDVI_l457).select('NDVI');



// Combine all landsat data, 1985 through 2015
var everything = ee.ImageCollection(lst5.merge(lst7));
everything = everything.merge(lst8);
everything = everything.merge(lst7_08);
everything = everything.merge(lst7_92);

print(everything);


//NDVI time-series 
// Create a time series chart for different land cover catergories.
// Define and display a FeatureCollection of three known locations.
var points = ee.FeatureCollection([
   ee.Feature(DEG2, {'label': 'Open Access Grazing'}),
  ee.Feature(GM2, {'label': 'Managed Grazing'}),
  ee.Feature(REF2, {'label': 'Nature Conservancy'}),
  ee.Feature(CRO2, {'label': 'Crops'})
]);


// Create a time series chart.
var NDVITimeSeriesAll = ui.Chart.image.seriesByRegion(
    everything, points, ee.Reducer.mean(), 'NDVI', 30, 'system:time_start','label')
        .setChartType('ScatterChart')
        .setOptions({
          title: 'Mean NDVI, plotted ~monthly, from 1984 to 2017 in 4 LC categories - Baringo Kenya',
          hAxis: {title: ' Date'}, 
          vAxis: {title: 'NDVI value (-1 to +1)', minValue: -0.0, maxValue: 0.8}, 
          lineWidth: 1,
          pointSize: 4,
          series: {
            0: {color: 'FF0000'}, // Unmanaged Grazing
            1: {color: '00FF00'}, // Managed Grazing
            2: {color: '0000FF'}, // Nature Conservancy
            3: {color: '00FFFF'}  // Cropland
}});

// Display.
print(NDVITimeSeriesAll);

person user21074    schedule 27.08.2018    source источник
comment
Можете ли вы создать воспроизводимый пример? Код, которым вы поделились, содержит множество объектов (таких как «Baringo», «DEG» и т. Д.), Которые, как я предполагаю, являются активами, которые вы загрузили сами. В настоящее время воспроизвести описанную вами ошибку невозможно.   -  person Ben DeVries    schedule 27.08.2018
comment
Привет, @BenDeVries, извиняюсь - я отредактировал код, включив в него геометрическую информацию для моих ресурсов, чтобы, надеюсь, сделать ее воспроизводимой. Спасибо, что посмотрели на мой вопрос.   -  person user21074    schedule 29.08.2018


Ответы (1)


Свойство system:time_start было потеряно на этапе маскировки. Это свойство необходимо для построения временных рядов, так как оно используется для построения оси времени. Измените эти две функции, чтобы переназначить это свойство изображению, которое возвращают функции, как показано ниже:

var maskL8SR = function(image) {
  // Bits 3 and 5 are cloud shadow and cloud, respectively.
  var cloudShadowBitMask = ee.Number(2).pow(3).int();
  var cloudsBitMask = ee.Number(2).pow(5).int();
  // Get the QA band.
  var qa = image.select('pixel_qa');
  // Both flags should be set to zero, indicating clear conditions.
 var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
              .and(qa.bitwiseAnd(cloudsBitMask).eq(0));
 return image
      // Scale the data to reflectance and temperature.
      .select(['B4', 'B5'], ['Red', 'NIR']).multiply(0.0001)
      .updateMask(mask)
      .set('system:time_start', image.get('system:time_start'));
 };

Эта последняя функция set() берет свойство system:time_start из исходного входного изображения и назначает его выходному изображению, гарантируя, что все изображения в вашей выходной коллекции ImageCollection включают исходные отметки времени. Благодаря функции set(), включенной в обе функции маскирования, я смог создать графики временных рядов, написанные в вашем коде.

person Ben DeVries    schedule 30.08.2018