1

I am relatively new to GEE, and I am trying to export my product (a mask) to Google Drive. However, when I use the Export.image.toDrive(), the tiff is a giant rectangle of 1 values. It should show up as a region of Argentina, with crop land (1) and non-cropland (0). Is there something wrong with my code?

Export.image.toDrive({
    image: classDiffIndex.clip(geometry), 
    description: ‘arg_r7_2016’, 
    folder: ‘cArg_GEE’, 
    scale: 30, 
    region: geometry,
    maxPixels: 130000000, 
    skipEmptyTiles: true, 
    formatOptions: {   
        cloudOptimized: true }
});

We thought it might be some sort of mistake where it was trying to read the values as 0 to 1 instead of 0 or 1, but looking into the .tif shows that they are saved as integers.

Full code:

// Por desarrollo = 0; else = 1
// For development = 0; else = 1
var disp = 0;

// las zonas pas desde la bosla - necesitas subirlas a GEE como assets -> table (*.shp, *.shx, *.dbf, *.prj, *.cpg)
//var zonaspas_limites = ee.FeatureCollection('users/bmunshel/zonaspas'); //https://code.earthengine.google.com/?asset=users/mhumber/Bolsa/zonaspas
var zonaspas_limites = ee.FeatureCollection('users/bmunshel/ZonasPAS').filterBounds(geometry); //https://code.earthengine.google.com/?asset=users/mhumber/Bolsa/zonaspas
//print(zonaspas_limites.filterBounds(geometry));
// pongalas en el mapa, puede filtrar los tambien: zonaspas_limites.filter(ee.Filter.eq('Zona PAS', 'VI'));
if (disp == 1){
    Map.addLayer(zonaspas_limites, {}, 'Zonas');
}

// fechas por cada zona (aaaa-mm-dd): 
// emp_temprano = 2 meses antes del primer dia de la siembra (suelo expuesto)
// fin_temprano = el primer dia de la siembra (suelo expuesto)
// emp_media = empieza de la temporana media, despues de la aparicion del cultivo (cultivo visible)
// fin_media = el premier dia de la cosecha (cultivo visible)
// Region II is very patchy, VI&VIII has a river showing as NDVI, X is flooded plains as NDVI, XV is incomplete
var zonas_fechas = {
    'I':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-06-15", fin_media:"2016-10-15", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'II':{emp_temprano:"2016-02-01" , fin_temprano:"2016-05-15", emp_media:"2016-06-01", fin_media:"2016-10-01", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'III':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-07-15", fin_media:"2016-10-15", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'IV':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-08-01", fin_media:"2016-11-07", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'V':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-08-07", fin_media:"2016-10-21", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'VI':{emp_temprano:"2016-02-01" , fin_temprano:"2016-07-01", emp_media:"2016-08-07", fin_media:"2016-11-01", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'VII':{emp_temprano:"2016-04-15" , fin_temprano:"2016-06-01", emp_media:"2016-08-15", fin_media:"2016-11-21", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'VIII':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-07-24", fin_media:"2016-11-15", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'IX':{emp_temprano:"2016-01-14" , fin_temprano:"2016-07-15", emp_media:"2016-08-14", fin_media:"2016-11-24", NDVI_despues_minimo:"1.3", NDVI_diferencia_minimo:"0.30"},
    'X':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-01", emp_media:"2016-08-14", fin_media:"2016-12-01", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"},
    'XI':{emp_temprano:"2016-02-01" , fin_temprano:"2016-07-15", emp_media:"2016-08-28", fin_media:"2016-12-07", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"},
    'XII':{emp_temprano:"2016-02-01" , fin_temprano:"2016-07-01", emp_media:"2016-09-01", fin_media:"2016-12-07", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"},
    'XIII':{emp_temprano:"2016-02-01" , fin_temprano:"2016-07-15", emp_media:"2016-08-07", fin_media:"2016-11-21", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"},
    'XIV':{emp_temprano:"2016-02-01" , fin_temprano:"2016-06-15", emp_media:"2016-08-21", fin_media:"2016-12-07", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"},
    'XV':{emp_temprano:"2016-04-01" , fin_temprano:"2016-07-14", emp_media:"2016-08-01", fin_media:"2016-10-14", NDVI_despues_minimo:"1.50", NDVI_diferencia_minimo:"0.30"}
};

function Landsat_NDVI(){
    // Coleccion de todas las imagenes Landsat, o puede usar Sentinel-2 (ee.ImageCollection("COPERNICUS/S2"))
    var imagenes = ee.ImageCollection("LANDSAT/LC08/C01/T1_TOA");

    // indices por buscando nubes y calculando NDVI; 
    // si usa Sentinel-2 es necesario cambiar 'B7' a 'B12', y 'B5' a 'B8a'. 'B4' es la misma por las dos
    var calidad_y_indices = function(imagen){
        var ndvi = imagen.normalizedDifference(['B5', 'B4']); //se llama 'nd'
        var suelos = imagen.normalizedDifference(['B5', 'B7']); //se llama 'nd_1'
        var nubes = ee.Algorithms.Landsat.simpleCloudScore(imagen);//imagen.normalizedDifference(['B7', 'B4']); //se llama 'cloud'
        var nubes_inv = ee.Image(100).subtract(nubes).add(suelos);
        return imagen
            .addBands(ndvi)
            .addBands(suelos)
            .addBands(nubes_inv);
    };

    // Buscar el pixel mejor por periodo antes de la siemba (sin nubes y suelo expuesto)
    var busca_suelos = function(zona_geom){
        var zona_id = zona_geom.properties["Zona PAS"];
        // selecciona las imagenes despues de la empieza y antes del fin
        var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_temprano, zonas_fechas[zona_id].fin_temprano)
            .filterBounds(zona_geom.geometry)
            .map(calidad_y_indices);
        // crea una imagen segun las imagenes y indices de la ImageCollection
        var img = imgs.qualityMosaic('cloud'); //Calidad de nubes
        //var img = imgs.median(); //Calidad de nubes
        var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
        return clipped;
    };

    // Buscar el pixel mejor por la temporana media (sin nubes y Maximum NDVI)
    var busco_cultivos = function(zona_geom){
        var zona_id = zona_geom.properties["Zona PAS"];
        // selecciona las imagenes despues de la empieza y antes del fin
        var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_media, zonas_fechas[zona_id].fin_media)
            .filterBounds(zona_geom.geometry)
            .map(calidad_y_indices);
        // crea una imagen segun las imagenes y indices de la ImageCollection
        var img = imgs.qualityMosaic('nd'); //Maximum NDVI (elimina numbes tambien)
        var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
        return clipped;
    };

    // Crear una ImageCollection con todas las imagenes tempranas (usando un indice de SWIR)
    var imcol_suelos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busca_suelos));
    var im_suelos = imcol_suelos.max()
    if (disp == 0){
        Map.addLayer(im_suelos, {'min': 0.04, 'max':0.7, 'bands':['B6', 'B5', 'B4']}, 'L8_Suelos');
    }

    // Crear una ImageCollection con todas las imagenes medianas (usando Maximum NDVI)
    var imcol_cultivos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busco_cultivos));
    var im_cultivos = imcol_cultivos.max()
    if (disp == 0){
        Map.addLayer(im_cultivos, {'min': 0.04, 'max':0.7, 'bands':['B6', 'B5', 'B4']}, 'L8_Cultivos');
    }

    return im_suelos.select(['nd'], ['NDVI_Antes']).addBands(im_cultivos.select(['nd'], ['NDVI_Despues']));
}

function Sentinel2_NDVI(){
    // Coleccion de todas las imagenes Landsat, o puede usar Sentinel-2 (ee.ImageCollection("COPERNICUS/S2"))
    var imagenes = ee.ImageCollection("COPERNICUS/S2");

    // indices por buscando nubes y calculando NDVI; 
    var calidad_y_indices = function(imagen){
        var ndvi = imagen.normalizedDifference(['B8A', 'B4']); //se llama 'nd'
        var suelos = imagen.normalizedDifference(['B8A', 'B12']); //se llama 'nd_1'
        var qa = imagen.select('QA60');
        // Bits 10 y 11 son nube y cirro.
        var cloudBitMask = 1 << 10;
        var cirrusBitMask = 1 << 11;
        // Usa calidad mascara y valor de Band 4 para eliminar las nubes. 
        var nubes_inv = qa.bitwiseAnd(cloudBitMask).eq(0).and(
            qa.bitwiseAnd(cirrusBitMask).eq(0)).and(
            imagen.select('B4').lt(2500)).and( //peak, 2500, the lower this number the more white on the right 
            imagen.select('B4').gt(500)); //min, 500, the higher this number, the more fields on left, more white on right 

        return imagen
            .divide(10000)
            .addBands(ndvi)
            .addBands(suelos)
            .updateMask(nubes_inv);
    };

    // Buscar el pixel mejor por periodo antes de la siemba (sin nubes y suelo expuesto)
    var busca_suelos = function(zona_geom){
        var zona_id = zona_geom.properties["Zona PAS"];
        // selecciona las imagenes despues de la empieza y antes del fin
        var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_temprano, zonas_fechas[zona_id].fin_temprano)
            .filterBounds(zona_geom.geometry)
            .map(calidad_y_indices);
        // crea una imagen segun las imagenes y indices de la ImageCollection
        var img = imgs.qualityMosaic('nd_1'); //Calidad de nubes
        var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
        return clipped;
    };

    // Buscar el pixel mejor por la temporana media (sin nubes y Maximum NDVI)
    var busco_cultivos = function(zona_geom){
        var zona_id = zona_geom.properties["Zona PAS"];
        // selecciona las imagenes despues de la empieza y antes del fin
        var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_media, zonas_fechas[zona_id].fin_media)
            .filterBounds(zona_geom.geometry)
            .map(calidad_y_indices);
        // crea una imagen segun las imagenes y indices de la ImageCollection
        var img = imgs.qualityMosaic('nd'); //Maximum NDVI (elimina numbes tambien)
        var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
        return clipped;
    };

    // Crear una ImageCollection con todas las imagenes tempranas (usando un indice de SWIR)
    var imcol_suelos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busca_suelos));
    var im_suelos = imcol_suelos.max();
    if (disp == 0){
        Map.addLayer(im_suelos, {'min': 0.04, 'max':0.48, 'bands':['B11', 'B8A', 'B4']}, 'S2_Suelos');
    }

    // Crear una ImageCollection con todas las imagenes medianas (usando Maximum NDVI)
    var imcol_cultivos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busco_cultivos));
    var im_cultivos = imcol_cultivos.max();
    if (disp == 0){
        Map.addLayer(im_cultivos, {'min': 0.04, 'max':0.48, 'bands':['B11', 'B8A', 'B4']}, 'S2_Cultivos');
    }

    return im_suelos.select(['nd'], ['NDVI_Antes']).addBands(im_cultivos.select(['nd'], ['NDVI_Despues']));
}

// NDVI por los dos sistemas
var L8NDVIs = Landsat_NDVI();
//var S2NDVIs = Sentinel2_NDVI();

// El mejor NDVI por cada pixel
// var NDVI_final_antes = ee.ImageCollection([L8NDVIs.select('NDVI_Antes'), S2NDVIs.select('NDVI_Antes')]).min().add(1);
// var NDVI_final_despues = ee.ImageCollection([L8NDVIs.select('NDVI_Despues'), S2NDVIs.select('NDVI_Despues')]).max().add(1);
var NDVI_final_antes = L8NDVIs.select('NDVI_Antes').add(1);
var NDVI_final_despues = L8NDVIs.select('NDVI_Despues').add(1);

// La diferencia 
var NDVI_dif = NDVI_final_despues.subtract(NDVI_final_antes).select(['NDVI_Despues'], ['NDVI_Diferencia'])
if (disp == 1){
    Map.addLayer(NDVI_dif, {min:-1, max:2}, 'NDVI_Diferencia');
};

// proporcion
var NDVI_pro = NDVI_final_despues.divide(NDVI_final_antes).select(['NDVI_Despues'], ['NDVI_Proporcion']);
if (disp == 1){
    Map.addLayer(NDVI_pro, {min:-1, max:3}, 'NDVI_Proporcion');
};

// todas las NDVI 
var NDVI_layer = NDVI_final_antes.addBands([NDVI_final_despues, NDVI_dif, NDVI_pro]);
if (disp == 1){
    Map.addLayer(NDVI_layer, {}, 'NDVI_Todo');
};

var aplicar_umbrales = function(zona_geom){
    var zona_id = zona_geom.properties["Zona PAS"];
    // Condiciones para Winter Crop
    var NDVI_despues_minimo = zonas_fechas[zona_id].NDVI_despues_minimo;
    var NDVI_diferencia_minimo = zonas_fechas[zona_id].NDVI_diferencia_minimo;
    var mapa = NDVI_layer.expression(
    '(dif >= '+NDVI_diferencia_minimo+') && '+'(des >= '+NDVI_despues_minimo+')',
    {
        dif: NDVI_layer.select('NDVI_Diferencia'),
        des: NDVI_layer.select('NDVI_Despues')
    }).rename('Cultivos');
    var clipped = mapa.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
    return clipped;
}

var imcol_cultivos_class = ee.ImageCollection(zonaspas_limites.getInfo().features.map(aplicar_umbrales));
var im_cultivos_class = imcol_cultivos_class.max()
Map.addLayer(im_cultivos_class, {min:0, max:1, palette:['000000', '66ff66']}, 'Cultivos_Final');

//this was in a function, might need it in a Map.addLayer(image, {bands: ['B4', 'B3', 'B2'], max: 0.5, gamma: 2});
var imagenes = ee.ImageCollection("COPERNICUS/S2");

//using bands to make prediction 
//var bands = ['B2','B3','B4','B8A','B11','B12','B2_1','B3_1','B4_1','B8A_1','B11_1','B12_1','nd','nd_2'];
var bands = ['B1','B2','B3','B4','B5','B6','B7','B8','B9','B10','B11','B1_1','B2_1','B3_1','B4_1','B5_1','B6_1','B7_1','B8_1','B9_1','B10_1','B11_1','nd','nd_2']

//making a feature colelction from the geometries created above (can do more than one classification)
var polygons = ee.FeatureCollection([
  ee.Feature(wintercrop, {'class': 1}),
  ee.Feature(nonwintercrop, {'class': 0}),
  ee.Feature(flooded_before, {'class': 0}),
  ee.Feature(flooded_after, {'class': 0}),
  ee.Feature(urban, {'class': 0}),
  ee.Feature(perm_water, {'class': 0}),
  ee.Feature(perm_soil, {'class': 0}),
  ee.Feature(unk_notwc, {'class': 0}),
  ee.Feature(unk_nodata, {'class': 0})
]);

//im_cultivos beings added for merge
var imagenes = ee.ImageCollection("COPERNICUS/S2");
var calidad_y_indices = function(imagen){
    var ndvi = imagen.normalizedDifference(['B8A', 'B4']); //se llama 'nd'
    var suelos = imagen.normalizedDifference(['B8A', 'B12']); //se llama 'nd_1'
    var qa = imagen.select('QA60');
    // Bits 10 y 11 son nube y cirro.
    var cloudBitMask = 1 << 10;
    var cirrusBitMask = 1 << 11;
    // Usa calidad mascara y valor de Band 4 para eliminar las nubes. 
    var nubes_inv = qa.bitwiseAnd(cloudBitMask).eq(0).and(
        qa.bitwiseAnd(cirrusBitMask).eq(0)).and(
        imagen.select('B4').lt(2500)).and(
        imagen.select('B4').gt(500));

    return imagen
        .divide(10000)
        .addBands(ndvi)
        .addBands(suelos)
        .updateMask(nubes_inv);
};
var busca_suelos = function(zona_geom){
    var zona_id = zona_geom.properties["Zona PAS"];
    // selecciona las imagenes despues de la empieza y antes del fin
    var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_temprano, zonas_fechas[zona_id].fin_temprano)
        .filterBounds(zona_geom.geometry)
        .map(calidad_y_indices);
    // crea una imagen segun las imagenes y indices de la ImageCollection
    var img = imgs.qualityMosaic('nd_1'); //Calidad de nubes
    var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
    return clipped;
};
var busco_cultivos = function(zona_geom){
    var zona_id = zona_geom.properties["Zona PAS"];
    // selecciona las imagenes despues de la empieza y antes del fin
    var imgs = imagenes.filterDate(zonas_fechas[zona_id].emp_media, zonas_fechas[zona_id].fin_media)
        .filterBounds(zona_geom.geometry)
        .map(calidad_y_indices);
    // crea una imagen segun las imagenes y indices de la ImageCollection
    var img = imgs.qualityMosaic('nd'); //Maximum NDVI (elimina numbes tambien)
    var clipped = img.clip(zona_geom.geometry).set("ZonaPAS", zona_id);
    return clipped;
};

var imcol_cultivos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busco_cultivos));
var im_cultivos = imcol_cultivos.max();
var imcol_suelos = ee.ImageCollection(zonaspas_limites.getInfo().features.map(busca_suelos));
var im_suelos = imcol_suelos.max();

//merge im_cultivos and im_suelos
var fullimagestack = ee.Image([im_cultivos, im_suelos]);

//get values for all pixels in each polygon for training purposes
var training = fullimagestack.sampleRegions({
  collection: polygons, //sample from polygons above (wintercrop and nonwintercrop)
  properties: ['class'], //keep this list of properties (0 and 1)
  scale: 30
}); 

//creates short vector machine classifier with custom parameters
var classifier = ee.Classifier.svm({
  kernelType: 'RBF', //radial basis function, gamma and cost are associated factors
  gamma: 0.5,
  cost: 10
}); 

//train classifier
var trained = classifier.train(training, 'class', bands);

//classify image 
var classified = fullimagestack.classify(trained); 
var cropMask = NDVI_dif.gt(0.18);
var cropFields = classified.updateMask(cropMask);

//display map
Map.addLayer(cropFields,
    {min: 0, max: 1, palette: ['000000', '66ff66']},
    'Winter Crops');

//attempt at filtering out non-field bits
var classDiffIndex = cropFields.gt(0);
var connCount = classDiffIndex.updateMask(classDiffIndex).connectedPixelCount(40,true);
var classDiffIndex = cropFields.updateMask(connCount.gt(39));
// var classDiffIndex = cropFields.where(connCount.gt(39), 0);
Map.addLayer(classDiffIndex,{min:0, max:1, palette:['000000', 'bb6666']},"Classified Difference Index L8")

Export.image.toDrive({
  image: classDiffIndex.clip(geometry),
  description: 'arg_r7_2016',
  folder: 'cArg_GEE',
  scale: 30,
  region: geometry,
  maxPixels: 130000000,
  skipEmptyTiles: true,
  formatOptions: {
    cloudOptimized: true
  }
});
6
  • Sorry about the formatting, not really sure how to do multiple lines of code on stackexchange
    – Blake M.
    Commented Jun 8, 2020 at 19:12
  • Use a triple backtic, as above
    – Vince
    Commented Jun 8, 2020 at 19:15
  • If you visualize classDiffIndex on a map and click around, what are the values reported in the console? Can you share a more complete script? Commented Jun 8, 2020 at 19:36
  • @JeremyMalczyk excuse me for the long code, but it is attached at the bottom of my original post now. It is pretty messy from multiple writers, and parts are in spanish, but I hope you are able to get the gist. The values are
    – Blake M.
    Commented Jun 8, 2020 at 19:52
  • @JeremyMalczyk [whoops the editing function times out FULL COMMENT:]excuse me for the long code, but it is attached at the bottom of my original post now. It is pretty messy from multiple writers, and parts are in spanish, but I hope you are able to get the gist. The values are 1 and 0 for crops and non-crops as they should be under the inspector.
    – Blake M.
    Commented Jun 8, 2020 at 20:04

1 Answer 1

1

The image you are exporting is not a mask. It is the cropFields image masked where connCount is greater than 39. You are visualizing it as a mask of sorts by scaling the values between 0 and 1 in the Map.addLayer call, but that is not what you are exporting. To export the mask, call .mask() on the image whose mask you want to export. Also, no need to clip the image to a region if you are passing that to Export.image.

var classDiffIndex = cropFields.updateMask(connCount.gt(39));
var classDiffIndexMask = classDiffIndex.mask();

Map.addLayer(classDiffIndexMask,{palette:['000000', 'bb6666']},"Classified Difference Index L8")

Export.image.toDrive({
  image: classDiffImageMask,
  description: 'arg_r7_2016',
  folder: 'cArg_GEE'
  scale: 30,
  region: geometry,
  maxPixels: 130000000,
  skipEmptyTiles: true,
  formatOptions: {
    cloudOptimized: true
  }
});
1
  • So unfortunately, that didn't work. It still exports the tiff as a solid rectangle of values, although this time they are all 0 instead of 1. We had the .clip because it would also mask the rest of the world, which I guess isn't really a problem.
    – Blake M.
    Commented Jun 9, 2020 at 14:55

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.