TransWikia.com

LS7 filling the gaps image with google earth engine

Geographic Information Systems Asked by delaye on April 21, 2021

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>>.

Any ideas are welcome !

2 Answers

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")

Correct answer by Kersten on April 21, 2021

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.

Answered by Giezi on April 21, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP