1st: The exact code you posted (https://code.earthengine.google.com/ce1a151ce06497b20cf1793715cb0120) did export the image correctly. So the error cannot be reproduced. May be, you changed the 'ROI' to a place where the filtered collection had no images.
2nd: There are no images because you filtered by cloud percentage, and so, it found images that suited the condition only in the left part of the ROI. If you comment like:
//.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE', 5))
you'll see that there are more images and you get the whole ROI (of course you get a part of the image plenty of clouds).
3rd: if automated exporting is your goal, maybe you should migrate to Python, but if you don't mind clicking the run button over and over, this would be one approach to download images only if the filtered collection has images (don't blame me on the getInfo
=):
//Define date range
var startDate = ee.Date.fromYMD(2017,7,1);
var endDate = ee.Date.fromYMD(2017,7,31);
//Load Sentinel-2 image collections
var coll_s2 = ee.ImageCollection("COPERNICUS/S2");
//Filter Sentinel-2 collection for ROI and cloud-coverage.
//Keep only images with less than 5% clouds
var coll_s2_filtered = coll_s2.filterDate(startDate, endDate)
.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE', 5))
.sort('system:time_start',false);
// Define the FeatureCollection!
var fc = ee.FeatureCollection(LIST_OF_POINT_FEATURES)
// Iterate over the FeatureCollection to create a List
// with images where there is data avialable
var listn = ee.List(fc.iterate(function(elem, ini){
var rectangle = ee.Feature(elem.buffer(20000).bounds());
var roi = rectangle.geometry();
var col = coll_s2_filtered.filterBounds(roi);
return ee.Algorithms.If(col.size(),
ee.List(ini).add(coll_s2_filtered.select(['B4','B3','B2']).mosaic().clip(roi)),
ee.List(ini))
}, ee.List([])))
listn = ee.List(listn)
print(listn)
// As Export is a Client-side function, you have to iterate the list
// in a client-side way
for (var n = 0; n<listn.size().getInfo(); n++) {
var i = ee.Image(listn.get(n))
Export.image.toDrive({
image: i,
description: 'image_'+n.toString(),
scale: 10,
folder: "tests",
region: i.geometry()
});
}
But if you want to change the filter regarding on whether it finds or not images, that would be different.
To get to your end goal of filtering your clipped image collection by 10% or less cloud cover, I would write a function that:
- counts the number of unmasked pixels in the image
- counts the number of pixels in the unmasked image
- calculates the percentage of masked pixels and sets this as a metadata property
I would then map this onto your image collection and filter it by the added metadata property.
Note that I'm assuming that your images are only masked by a cloud mask.
function get_cloud_cover_roi(image){
var Peyto_pixelscount = image.select('ALBEDO').reduceRegion({
reducer: ee.Reducer.count(),
geometry: image.geometry(),
scale: 30,
maxPixels: 1e9
}).get('ALBEDO')
var npix = image.select('ALBEDO').unmask().reduceRegion({
reducer: ee.Reducer.count(),
geometry: image.geometry(),
scale: 30,
maxPixels: 1e9
}).get('ALBEDO')
var cloud_cover_roi = ee.Number(1)
.subtract(ee.Number(Peyto_pixelscount).divide(npix))
.multiply(100)
return image.set('cloud_cover_roi', cloud_cover_roi)
}
var Peytoclip_filtered = Peytoclip
.map(get_cloud_cover_roi)
.filterMetadata('cloud_cover_roi', 'less_than', 10)
Best Answer
Since you said that you tried
clamp()
, I'm assuming that you want the values reclassified.https://code.earthengine.google.com/5245cc7b6205254f99f3e888b785659c