0

I am a beginner with Google Earth Engine (GEE). When I select a large area of interest to obtain Landsat 8 imagery in GEE, I find that even when I use a whole year's data, the final image still has areas with no data. Time-wise, I'm mainly looking at that one year because I will need to process images from different years afterwards. So I'm looking for a better method to solve this problem. Although I've also read about spatial interpolation and image fusion, including the need to consider the impact of striping when dealing with Landsat 7 images, I'm not sure how to proceed. I would like to know how to fill the gaps in Landsat 8 imagery with Landsat 7 images in large areas, or fill in Landsat 7 with Landsat 5 images. I hope you can point me in the right direction and provide the relevant code.

var geometry = 
    /* color: #d63000 */
    /* shown: false */
    /* displayProperties: [
      {
        "type": "rectangle"
      }
    ] */
    ee.Geometry.Polygon(
        [[[-124.24744923114777, 48.922751015268005],
          [-124.24744923114777, 28.072318365921276],
          [-70.37049610614778, 28.072318365921276],
          [-70.37049610614778, 48.922751015268005]]], null, false);
var roi = geometry;
var year = 2014;
var startDate = year + '-01-01';
var endDate = year + '-12-31';
function maskL8sr(image) {
  // Bit 0 - Fill
  // Bit 1 - Dilated Cloud
  // Bit 2 - Cirrus
  // 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 thermalBands = image.select('ST_B.*').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(thermalBands, null, true)
      .updateMask(qaMask)
      .updateMask(saturationMask)
      // added this to get time stamp for time series
      .copyProperties(image, ["system:time_start"]);
}

var landsat8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterBounds(roi)
    .filterDate(startDate, endDate)
    .map(maskL8sr)
    .select('SR_B2','SR_B3','SR_B4','SR_B5','SR_B6','SR_B7')
    .median()
    .clip(roi);
    
var visualization = {
  bands: ['SR_B4', 'SR_B3', 'SR_B2'],
  min: 0.0,
  max: 0.3,
};
 
Map.addLayer(landsat8, visualization, "True Color (432)");
Map.centerObject(roi)
3
  • Thank you very much to Padmanabha for the edits and corrections, which improved my help request post. I apologize, as it was my first time asking on this website, and I didn't format my code properly.
    – ronghui
    Nov 1, 2023 at 5:53
  • it'd be very important that you share the geometry, 'cos making a fake (testing) one could not be enough to reproduce the error Nov 1, 2023 at 23:09
  • I apologize for forgetting to share my geometry. I have now added the extent of my area of interest, which is quite large. I am currently facing a major challenge with a large-scale study and am troubled by areas with no data. Even the Landsat 8 imagery seems to be affected by striping, and I'm not sure if this is due to the large area or the impact of cloud removal. However, it seems that there would still be gaps if I don't perform cloud removal.
    – ronghui
    Nov 2, 2023 at 1:20

1 Answer 1

0

It is really a big area for testing, so, I tested my code in a much smaller area, to get results faster.

// Isla de los Estados
var geometry = 
    /* color: #98ff00 */
    /* shown: false */
    /* displayProperties: [
      {
        "type": "rectangle"
      }
    ] */
    ee.Geometry.Polygon(
        [[[-64.80766187430255, -54.63906262127111],
          [-64.80766187430255, -54.95572474537549],
          [-63.752974374302546, -54.95572474537549],
          [-63.752974374302546, -54.63906262127111]]], null, false);

var roi = geometry;
var year = 2014;
var startDate = year + '-01-01';
var endDate = year + '-12-31';
function maskL8sr(image) {
  // Bit 0 - Fill
  // Bit 1 - Dilated Cloud
  // Bit 2 - Cirrus
  // 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 thermalBands = image.select('ST_B.*').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(thermalBands, null, true)
      .updateMask(qaMask)
      .updateMask(saturationMask)
      // added this to get time stamp for time series
      .copyProperties(image, ["system:time_start"]);
}
// same up to here

var landsat8 = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
    .filterBounds(roi)
    .filterDate(startDate, endDate)
    // add a band for qualityMosaic. Higher number will be at top
    // I did: L8 = 3, L5 = 2, L7 = 1 (you can change it for your own convinance) 
    .map(function(i){return i.addBands(ee.Image(3).rename('order'))})
    .map(maskL8sr)
    .select('SR_B2','SR_B3','SR_B4','SR_B5','SR_B6','SR_B7','order')
    .median()
    // match datatype for mosaicking
    .toFloat()
    // unify bands with L7 and L5 to be able to mosaic
    .rename(["blue", "green", "red", "nir", "swir1", "swir2",'order'])
    .clip(roi);

var landsat7 = ee.ImageCollection("LANDSAT/LE07/C02/T1_L2")
           .filterBounds(roi)
           .filterDate(startDate, endDate)
           .map(function(i){return i.addBands(ee.Image(1).rename('order'))})
           .map(maskL8sr)
           .select('SR_B1', 'SR_B2','SR_B3','SR_B4','SR_B5','SR_B7','order')
           .median()
           .toFloat()
           .rename(["blue","green","red","nir","swir1","swir2",'order'])
           .clip(roi);

var landsat5 = ee.ImageCollection("LANDSAT/LT05/C02/T1_L2")
           .filterBounds(roi)
           .filterDate(startDate, endDate)
           .map(function(i){return i.addBands(ee.Image(2).rename('order'))})
           .map(maskL8sr)
           .select('SR_B1', 'SR_B2','SR_B3','SR_B4','SR_B5','SR_B7','order')
           .median()
           .toFloat()
           .rename(["blue","green","red","nir","swir1","swir2",'order'])
           .clip(roi);

// create a collection and mosaic using a quality band (order)
var final = ee.ImageCollection.fromImages([landsat8, landsat7, landsat5]).qualityMosaic("order")

// alternatively you can use `.blend` but you gotta be sure of not having empty 
// collections (as in this case, that L5 is empty)
// var final = landsat7.blend(landsat5).blend(landsat8)

var visualization = {
  bands: ['red', 'green', 'blue'],
  min: 0.0,
  max: 0.2,
};
 
Map.addLayer(final, visualization, "True Color (432)");
Map.centerObject(roi)

// visualize the order (satellites)
Map.addLayer(final, {bands:["order"], min:1, max:3, palette:["red", 'green', "blue"]}, "satellites")

Be aware that, for the example, I didn't pay much attention to the cloud masking method.

link: https://code.earthengine.google.com/46ce1eee8fb34dea1b5f7616f2271545

1
  • Thank you for the test. I have also looked into NDVI related fill-ins, but currently, when running my code, I have not considered Sentinel imagery data. Thus, in some respects, I cannot take into account the Sentinel imagery data. It must be said that in my discussions with my teacher, some of the blank areas might be due to snow or similar reasons. However, what is peculiar is that even under Landsat 8 imagery, there are still some noticeable color discrepancies and striping issues across large areas of the image, which is quite troubling for me. I hope to receive more help with this.
    – ronghui
    Nov 4, 2023 at 8:14

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.