I'm trying to make an annual composite of Landsat 5 data for a region of interest in Google Earth Engine but what I end up with is hazy and cloudy. I've tried filtering for haze and clouds but still get both in my final version.

The code I have written is below

 roi =
    [[[-70.94315884724863, -13.228382487713638],
      [-68.53715298787363, -13.228382487713638],
      [-68.53715298787363, -12.022330477798716],
      [-70.94315884724863, -12.022330477798716],
      [-70.94315884724863, -13.228382487713638]]]);
var clouds = function(image) {
 var qa = image.select('pixel_qa');
 var cloud = qa.bitwiseAnd(1 << 5)
              .and(qa.bitwiseAnd(1 << 7))
              .or(qa.bitwiseAnd(1 << 3));
 var mask2 = image.mask().reduce(ee.Reducer.min());
 return image.updateMask(cloud.not()).updateMask(mask2);

function lsHazeMask(image) { 
var mask = image.select('sr_atmos_opacity').lte(300);
return image.updateMask(mask);

var jsonCoordString = roi.toGeoJSON();

for (var start_year = 1986; start_year <= 1990; start_year++)
var startDate = ee.Date.fromYMD(start_year,01,01);
var sr = ee.ImageCollection(ls5SR).filter(ee.Filter.bounds(roi)).filter(ee.Filter.calendarRange(6,9,'month')).filterMetadata('CLOUD_COVER', 'less_than', 30).filter(ee.Filter.date(startDate,startDate.advance(1,'year')));
sr = sr.map(clouds);
sr = sr.map(lsHazeMask);
sr = sr.reduce(ee.Reducer.median());

Map.addLayer(sr.select([2,1,0]).clip(roi),{min: [0,0,0], max: [2000,2000,2000]},'puerto'+start_year);

2 Answers 2


You will need to extend the date range for the composites. You just have 2-3 images in each composite. That is insufficient to make a correct median image composite.

You can check the number of images which a pixel is made of using the count reducer:

var srCount = sr.select([0]).reduce(ee.Reducer.count());
Map.addLayer(srCount.clip(roi),{min: 0, max: 20},'puertoCount'+start_year);


  • thank you for this! I found that if I allowed images from the full year - it was shockingly even cloudier and worse quality throughout. But maybe combining this with @Daniel Weill's comment will help
    – Rachel
    Apr 16, 2020 at 17:58

The pixel_qa band for Landsat 5 can be a bit hit-and-miss. You might want to complement this band with some cloud scoring algorithm. Here is an example of an implementation. It's quite aggressive and will mask out much of built-up areas, while still not getting all haze. So, room for improvements. Like @Kuik points out, you will certainly get better results if you include more imagery.

  • thank you for this! I will try to implement the cloud scoring algorithm. I ended up with so few images because if I let it pull from the whole year (Tropical forest so basically super cloudy most days of October - May) then the resulting image was 100% clouds, so narrowing the dates let me get at least some land cover haha. But maybe this cloud algorithm you've linked will help me get around this and then I can use the full year's dates. :)
    – Rachel
    Apr 16, 2020 at 18:00

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.