1

I am downloading images from Google Earth Engine's Landsat 8 Collection 1 Tier 1 8-Day EVI Composite collection here. I would like to create one image, a median composite of the images from May 1st to August 31st in a year and I would like to filter for clouds.

I want to filter the collection for clouds, however, there is not a cloud tag available in the dataset so the cloud filter function does not work. There's also not a "QA_PIXEL" to filter out for the best pixel. Someone suggested to me that to filter for clouds I could keep the range of EVI values from 0 to 1, as negative values are often associated with clouds, but I'm not sure how accurate that is. The EVI collection itself is already a composite, but I can't find any documentation regarding whether they already filtered for clouds. I have looked through the google earth engine github repository and elsewhere.

Here is the code I have. Does this look like a good way to filter for clouds and obtain the median? Should I put back in the negative values to get a more accurate median?

// Define the state shape of California
var california = ee.FeatureCollection('TIGER/2018/States')
  .filter(ee.Filter.eq('NAME', 'California'));

// Extract the geometry of California
var roi = california.geometry();

// Load Landsat 8
var eviCol = ee.ImageCollection("LANDSAT/LC08/C01/T1_8DAY_EVI") 
  .filterDate('2021-05-01', '2021-08-31')
  .filterBounds(roi)
  .select('EVI');

// Create a cloud mask based on 'EVI' values
var cloudMasked = eviCol.map(function(image) {
  var eviThreshold = 0; // Adjust the EVI threshold as needed
  return image.updateMask(image.gte(eviThreshold));
});

// Calculate the median composite from the cloud-masked collection
var medianComposite = cloudMasked.median();

// Visualize the median composite with min set to 0 to mask out negative values
var colorizedVis = {
  min: 0, // Set min to 0 to mask out negative values
  max: 1,
  palette: [
    'ffffff', 'ce7e45', 'df923d', 'f1b555', 'fcd163', '99b718', '74a901',
    '66a000', '529400', '3e8601', '207401', '056201', '004c00', '023b01',
    '012e01', '011d01', '011301'
  ],
};
Map.addLayer(medianComposite.clip(roi), colorizedVis, 'Cloud-Filtered Median Composite');

// Export the median composite image to Google Drive
Export.image.toDrive({
  image: medianComposite,
  description: 'Landsat2021California_MedianComposite',
  scale: 30,
  region: roi,
  maxPixels: 1e13
});
1

1 Answer 1

1

You could calculate the EVI yourself, from the "plain" Landsat 8 collection. That would give you more control over the cloud masking. Something like this:

// Define the state shape of California
var california = ee.FeatureCollection('TIGER/2018/States')
  .filter(ee.Filter.eq('NAME', 'California'));

// Extract the geometry of California
var roi = california.geometry();
print(ee.ImageCollection('LANDSAT/LC08/C02/T1_L2').first())
var collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
  .filterDate('2021-05-01', '2021-08-31')
  .filterBounds(roi)
  .map(function (image) {
    var rescaled = image
      .select('SR_B.')
      .multiply(0.0000275).add(-0.2)
    var evi = ee.Image()
      .expression(
        'G * ((nir - red) / (nir + C1 * red - C2 * blue + L))', {
          blue: rescaled.select('SR_B3'),
          red: rescaled.select('SR_B4'),
          nir: rescaled.select('SR_B5'),
          i: rescaled,
          L: 1,
          C1: 6,
          C2: 7.5,
          G: 2.5
        }
      )
      .clamp(-1, 1)
    var qa = image.select('QA_PIXEL')
    var cloudFree = bitwiseExtract(qa, 6)
    var water = bitwiseExtract(qa, 7)
    return evi
      .updateMask(cloudFree.or(water))
  })

var median = collection
  .median()
  .clip(roi)
  
Map.addLayer(median, {min: 0, max: 1, 
  palette: [
      'ffffff', 'ce7e45', 'df923d', 'f1b555', 'fcd163', '99b718', '74a901',
      '66a000', '529400', '3e8601', '207401', '056201', '004c00', '023b01',
      '012e01', '011d01', '011301'  
  ]
})
Map.centerObject(roi)


function bitwiseExtract(value, fromBit, toBit) {
  if (toBit === undefined)
    toBit = fromBit
  var maskSize = ee.Number(1).add(toBit).subtract(fromBit)
  var mask = ee.Number(1).leftShift(maskSize).subtract(1)
  return value.rightShift(fromBit).bitwiseAnd(mask)
}

https://code.earthengine.google.com/c4b980e775dbbc5da03e3cc286d0b2e9

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.