3

I used the following script to export an image from Earth Engine. I am trying to specify the crs_transform parameter argument in the Export.image.toDrive function using the "transform" property of the image's ee.Projection object. I can see that when I print the image's projection object that there is a field for "transform" containing a valid array element, but the export function throw's an error:

Invalid "argument, crs transform was not a string or array"

How can I retrieve the image's CRS transform?

var geometry = ee.Geometry.Rectangle([-114.3, 51.2, -113.8, 50.8]);
  
var S2_collection = ee.ImageCollection("COPERNICUS/S2_SR_HARMONIZED")
  .filterDate('2019-08-01', '2019-08-30')
  .filterBounds(geometry) 
  // ...map a cloud masking function
    
var S2_mosaic = S2_collection.median()
    
var projection = S2_mosaic.projection();
print(projection)
    
Export.image.toDrive({
  image: S2_mosaic,
  description: 'imageToDriveExample_transform',
  crs: projection.crs,
  crsTransform: projection.transform,  // <-- here's the problem
  region: geometry
});
1

1 Answer 1

1

You are calling projection.transform as if the projection variable is a JavaScript literal object, but it is an Earth Engine server-side ee.Projection object whose properties cannot be accessed by dot or bracket notation. You need to transfer the ee.Projection object client-side to work with it as a JavaScript literal object; you can use the evaluate function to do this:

projection.evaluate(function(proj_obj) {
  Export.image.toDrive({
    image: S2_mosaic,
    description: 'imageToDriveExample_transform',
    crs: proj_obj.crs,
    crsTransform: proj_obj.transform,
    region: geometry });
});

Here is some information on server vs client.

Also, the default CRS transform for image collection reductions (e.g. ee.Image.median) is 1-degree pixel scale in WGS84 EPSG:4326 projection. My guess is that it not what you want. If you'd like your export CRS to match the CRS of some other image in the collection, you should get it from an unaltered image like S2_collection.first().projection(). Here is more information on the default projection.

5
  • very helpful, thanks! Also very non-intuitive to me why the typical workaround to the "client-side vs. server-side" challenge-- that is, using .getInfo()-- doesn't work in this case. E.g., crsTransform: projection.transform().getInfo()
    – mikoontz
    Commented Jan 6, 2023 at 20:54
  • 1
    The CRS transform is a weird case where there is not an EE method to fetch it i.e. ee.Projection.transform is not a method like ee.Projection.crs' or ee.Projection.nominalScale()` are. The CRS transform can only be accessed from the client-side representation of the ee.Projection object. Commented Jan 9, 2023 at 16:47
  • Interesting! So even though ee.Projection.transform() exists, it's not doing something equivalent to ee.Projection.crs() or ee.Projection.nominalScale()?
    – mikoontz
    Commented Jan 10, 2023 at 18:14
  • It returns a result that is not compatible with the crsTransform parameter. Try var foo = ee.Projection('EPSG:4326').transform().aside(print) and see that it is not formatted as [xScale, xShearing, xTranslation, yShearing, yScale, yTranslation] Commented Jan 10, 2023 at 21:15
  • the answer it is not complete. You can retrieve crs transform and use it as input to export an image by using S2_collection.first().projection().getInfo()['transform'] Commented Nov 28 at 20:21

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