0

In Google Earth Engine I am calculating Sentinel-2 NDVI and then want to rescale my ndvi imagery from 10m to 30m to match Landsat. Finally, I want to combine the 30m Sentinel-2 with the Landsat imagery to give a two band image and export them in a specific projection (UTM). I know that with composites (such as ndvi) the projection information is lost. I have tried to correct for this but my code below doesn't seem to work - plotting the data shows the Sentinel-2 is still at 10m. And if I try and export the data I get the error "Error: Can't transform (224518.0,-661010.5)".

How can I reassign the projection correctly and create a 30m resolution ndvi image for Sentinel-2?

All the other examples I can find are for simple images rather than composites.

// Cloud mask Landsat 8
function cloudMaskL8sr(image) {
  var cloudShadowBitMask = (1 << 3);
  var cloudsBitMask = (1 << 5);
  var qa = image.select('QA_PIXEL');
  var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
                 .and(qa.bitwiseAnd(cloudsBitMask).eq(0));
  return image.multiply(0.0000275).add(-0.2).updateMask(mask);
}

// Cloud mask using the Sentinel-2 QA band.
function maskS2clouds(image) {
  var qa = image.select('QA60');
  var cloudBitMask = Math.pow(2, 10);
  var cirrusBitMask = Math.pow(2, 11);
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
             qa.bitwiseAnd(cirrusBitMask).eq(0));
  return image.divide(10000).updateMask(mask).copyProperties(image, ['system:time_start']);
}

// Get landsat 8 collection
var ls8_collection = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2") 
                      .filterBounds(geometry) 
                      .filterDate(ee.Date.fromYMD(2020,1,1),ee.Date.fromYMD(2020,12,31))
                      .map(cloudMaskL8sr)
                      .select(['SR_B4','SR_B5']);

// Calculate landsat ndvi                      
var ls8_ndvi = ls8_collection
                .median()
                .normalizedDifference(['SR_B5','SR_B4'])
                .clip(geometry)
                .rename('LS8_NDVI');

// reset scale and projection                
ls8_ndvi =  ls8_ndvi.setDefaultProjection({
    crs: 'EPSG:32360',
    scale: 30
    }) 
                      
// Get Sentinel-2 data
var s2_collection = ee.ImageCollection('COPERNICUS/S2_SR')
                      .filterBounds(geometry)
                      .filterDate(ee.Date.fromYMD(2020,1,1),ee.Date.fromYMD(2020,12,31))
                      .filterMetadata('CLOUDY_PIXEL_PERCENTAGE','less_than',50) // Need to include this to reduce teh amount of data
                      .map(maskS2clouds)
                      .select(['B4','B8'])      
                      
// calculate ndvi
var s2_ndvi = s2_collection
                .median()
                .normalizedDifference(['B8','B4'])
                .clip(geometry)
                .rename('S2_NDVI');                     
                
// Change resolution and assign projection
s2_ndvi =   s2_ndvi.setDefaultProjection({
    crs: 'EPSG:32360',
    scale: 30
    })                

// Combine Landsat and Sentinel-2 into a single two-band image
var combined = ee.Image.cat([s2_ndvi,ls8_ndvi])
print(combined)

// Plot (as a test)
var ndviParams = {min:-0.25, max:1, palette:'CE7E45,DF923D,F1B555,FCD163,99B718,74A901,66A000,529400,3E8601,207401,056201,004C00,023B01,012E01,011D01,011301'}; 
Map.addLayer(s2_ndvi, ndviParams, 'S2');
Map.addLayer(ls8_ndvi, ndviParams, 'LS8');

// Export image to drive
Export.image.toDrive({
  image: combined,
  description : 'combined',
  scale : 30,
  crs: 'EPSG:32360',
  region : geometry
})

1 Answer 1

1

Your geometry isn't listed, but most likely it exceeds the bounds of the UTM projection you're using. That projection is only valid for 6 degrees of longitude.

2
  • Good thought, thanks for the pointer. It does explain the error message on the export. BUT no, that's not the issue. I've now set the AOI to be a box around the city of Sheffield, UK; an area ~15km by 11km. That's pretty much in the middle of that UTM zone. But it still won't export "Export too large: specified 1390226400 pixels (max: 100000000)." I realize I can change max pixels but ultimately I want to export a whole Landsat scene. Furthermore, the map display is showing that the S-2 imagery is still at 10m resolution not 30m resolution so I'm still not getting this right somewhere.
    – Ddee
    Aug 20, 2021 at 12:34
  • You're expected in increase maxPixels as necessary. That's only 1G, so it shouldn't be a problem. Setting the default projection doesn't do anything, it just sets a guide. If you really want to reproject pixels to 30m, use reproject(), not defaultProjection. But the export, running at 30m, is going to do that automatically. Aug 21, 2021 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.