9

I would like to work with Landsat 7 images, but most of them have gaps... I would like to fill the Gaps by aggregate images bands by month. So I'm looking for a way to deal with this problem. I have tried to create a composite image with

var collectionLS7 = ee.ImageCollection('LANDSAT/LE7_L1T_TOA') //10m
    // Select the bands of interest to avoid taking up memory.
    .select(bandNames)
    // Filter to get only imagery at a point of interest.
    .filterBounds(roi);
var composite = collectionLS7.median();

But it doesn't work enter image description here I have also tried

var customComposite = ee.Algorithms.Landsat.simpleComposite({
  collection: collectionLS7,
  percentile: 75,
  cloudScoreRange: 5,
  maxDepth: 4
});

But with an error Layer 1: Layer error: ImageCollection.reduce: Error in map(ID=LE72040492015361ASN01): Landsat.TOA: Band 'B1' is Type<Float>, expected Type<Short<0, 255>>.

3 Answers 3

16

You could try filling the gaps before you aggregate them by month.

USGS published a LS7 SLC-off gap-filling algorithm.

This algorithm was recreated for Google Earth Engine by Noel Gorelick: https://code.earthengine.google.com/d20cba5268ccbe117e2fc1c5fefc33f3

Building upon this Genadii Donchyts changed the algorithm for faster performance: https://code.earthengine.google.com/2ead14966758793579dfb31b94855275

The relevant thread can be found on the Google Earth Engine Developers messaging board (after registration).

For completeness, here is the relevant function from Noel Gorelicks Code:

var MIN_SCALE = 1/3;
var MAX_SCALE = 3;
var MIN_NEIGHBORS = 144;

/* Apply the USGS L7 Phase-2 Gap filling protocol, using a single kernel size. */
var GapFill = function(src, fill, kernelSize) {
  var kernel = ee.Kernel.square(kernelSize * 30, "meters", false)
  
  // Find the pixels common to both scenes.
  var common = src.mask().and(fill.mask())
  var fc = fill.updateMask(common)
  var sc = src.updateMask(common)

  // Find the primary scaling factors with a regression.
  // Interleave the bands for the regression.  This assumes the bands have the same names.
  var regress = fc.addBands(sc)
  regress = regress.select(regress.bandNames().sort())
  var fit = regress.reduceNeighborhood(ee.Reducer.linearFit().forEach(src.bandNames()),  kernel, null, false)
  var offset = fit.select(".*_offset")
  var scale = fit.select(".*_scale")

  // Find the secondary scaling factors using just means and stddev
  var reducer = ee.Reducer.mean().combine(ee.Reducer.stdDev(), null, true)
  var src_stats = src.reduceNeighborhood(reducer, kernel, null, false)
  var fill_stats = fill.reduceNeighborhood(reducer, kernel, null, false)
  var scale2 = src_stats.select(".*stdDev").divide(fill_stats.select(".*stdDev"))
  var offset2 = src_stats.select(".*mean").subtract(fill_stats.select(".*mean").multiply(scale2))

  var invalid = scale.lt(MIN_SCALE).or(scale.gt(MAX_SCALE))
  scale = scale.where(invalid, scale2)
  offset = offset.where(invalid, offset2)

  // When all else fails, just use the difference of means as an offset.  
  var invalid2 = scale.lt(MIN_SCALE).or(scale.gt(MAX_SCALE))
  scale = scale.where(invalid2, 1)
  offset = offset.where(invalid2, src_stats.select(".*mean").subtract(fill_stats.select(".*mean")))

  // Apply the scaling and mask off pixels that didn't have enough neighbors.
  var count = common.reduceNeighborhood(ee.Reducer.count(), kernel, null, true, "boxcar")
  var scaled = fill.multiply(scale).add(offset)
      .updateMask(count.gte(MIN_NEIGHBORS))

  return src.unmask(scaled, true)
}

var source = ee.Image("LANDSAT/LE7_L1T/LE70440342016075EDC00")
var fill = ee.Image("LANDSAT/LE7_L1T/LE70440342016027EDC00")
3

What @Kersten proposed is perfect, but I would just like to answer to the specific

 Band 'B1' is Type<Float>, expected Type<Short<0, 255>>

error, which I also get after gap filling, when trying to apply the simpleComposite algorithm.

You can change the type of the image like this:

var imageCollection= imageCollection.map(function(img){
        return img.toByte()
      });

You should then be able to run the simpleComposite algorithm.

0

I tried the code for LANDSAT/LE07/C02/T1_L2 but I received the following error: Line 10: src.mask is not a function

1
  • 1
    If you have a new question, please ask it by clicking the Ask Question button. Include a link to this question if it helps provide context. - From Review
    – Vince
    Commented Apr 18, 2023 at 4:49

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.