2

I need assistance for solving a problem with Landsat 5 surface reflectance image's cloud mask.

I am new to this tool/programming and want to try this tool to process cloud mask. Through the provided open source code in the web page of Goole Earth Engine, the processing code is composed as below.

However, I would like to request help to debug this error message "Error: Invalid argument: 'image' must be of type Image."


var cloudy_scene = ee.Image('LANDSAT/LT5_SR/LT5*************');

Map.centerObject(cloudy_scene);

Map.addLayer(cloudy_scene,{},'all_bands_cloud');

// Load a Landsat 5 image collection.
var collection = ee.ImageCollection("LANDSAT/LT5_SR")

// Filter to get a geometry representing an export region.
.filterBounds(ee.Geometry.Rectangle([***.***,**.***,***.***,**.***]))

// Filter to get the years/months/days of data.
.filterDate('1993-01-01', '1993-03-01')  // filter to your favorite period

// Sort the collection in chronological order.
.sort('system:time_start', true);

//Details for cfmask
//0=clear
//1=water
//2=shadow
//3=snow
//4=cloud

var masked = collection.map(function(image){  
    return image.updateMask(cloudy_scene.select(['cfmask']).neq(4))
});

// Apply the mask to the image and display the result.
Map.addLayer(masked, {}, 'masked');

var geometry = ee.Geometry.Rectangle([***.***,**.***,***.***,**.***]);

//export the image, specifying scale and region.
Export.image.toDrive({
    image: masked,
    description: 'ImageToDrive',
    scale: 30,
    region: geometry
});
  • I'm not 100% sure what your goal is. Do you want to apply cloud masking to a specific image or an entire image collection? If it's the latter you could try exchanging var masked = collection.map(function(image){ return image.updateMask(cloudy_scene.select(['cfmask']).neq(4)) }); with var masked = collection.map(function(image){ return image.updateMask(image.select(['cfmask']).neq(4)) }); and see if that's what you need – Val Jun 5 '17 at 8:14
  • Thank Jochen for your reply. Actually, I would like to apply cloud masking to the specific image "cloudy_scene". I also tried your suggestion, however, I still received the error message "Error: Invalid argument: 'image' must be of type Image." – Jacob_Fox Jun 5 '17 at 9:03
  • Can you share the id of your cloudy_scene? In your example, there's just asterisks – Val Jun 5 '17 at 9:04
  • Thanks again for your reply. My id is 'LANDSAT/LT5_SR/LT51170431993035'. Sorry for that I used asterisks. I supposed that the hidden ID does not influence on your suggestion. Other asterisks are [122.006687,24.673089,121.282702,25.300515] for my geometry. I hope the updated information could be beneficial for your suggestion. Thanks in advance! – Jacob_Fox Jun 6 '17 at 0:40
2

Ok, interestingly your script ran through without giving me any error. But if you want to mask out clouds and shadows in your specific image (as you said in your comment) you can do it like this:

//cloudy image
var cloudy_scene = ee.Image('LANDSAT/LT5_SR/LT51170431993035');
Map.centerObject(cloudy_scene);

// add true color composite to map
Map.addLayer(cloudy_scene,{min:0,max:3000,bands:['B3','B2','B1']},'cloudy');

//Details for cfmask
//0=clear
//1=water
//2=shadow
//3=snow
//4=cloud

// select cfmask band as mask
var msk = cloudy_scene.select('cfmask');

//conditions which to mask out - no shadows, snow or clouds
msk = msk.neq(2).and(msk.neq(3)).and(msk.neq(4));

// apply mask
var masked = cloudy_scene.mask(msk)

// add masked image to Layer
Map.addLayer(masked,{min:0,max:3000,bands:['B3','B2','B1']},'masked');

//  rectangle for export
var geometry = ee.Geometry.Rectangle(122.006687,24.673089,121.282702,25.300515);

// Select bands for export
var bnds = ['B1','B2','B3','B4','B5','B7'];

//export the image, specifying scale and region.
Export.image.toDrive({
    image: masked.select(bnds),
    description: 'MaskedLS5',
    scale: 30,
    region: geometry
});

Edit:

GEE requires the data types of an image to be identical if you want to export it. If you print the masked image to the console you'll see that there are additional 8bit bands. I assumed you're interested in the surface reluctance only, so I added a list of bands for export and I select them within the export function.

If you want to export all bands, you need to cast them in a common datatype like uint16.

  • I am grateful to you for the revised code. I learn a lot from your suggestion, as well as your programming style (easy-to-read and very clear). Thanks again. – Jacob_Fox Jun 7 '17 at 1:11
  • It almost works well if this error message "Error: Exported bands must have compatible data types; found inconsistent types: Int16 and Byte." can be overcome. – Jacob_Fox Jun 7 '17 at 3:48
  • Sorry, I haven't actually exported the image. I've updated my answer and it should work now. – Val Jun 7 '17 at 7:23
  • Thanks for your great help. It can perfectly work without generating any error message. I appreciate your remarkable suggestions. Thanks again. – Jacob_Fox Jun 7 '17 at 8:55
0

I would suggest using the more accurate pixel_qa mask over cfmask for Landsat 5 Surface Reflectance as recommended here. Also here is the modified version of @Val's answer:

//cloudy image
var cloudy_scene = ee.Image('LANDSAT/LT05/C01/T1_SR/LT05_135040_19900517');
Map.centerObject(cloudy_scene);

// add true color composite to map
Map.addLayer(cloudy_scene,{min:0,max:3000,bands:['B3','B2','B1']},'cloudy');

// Details for pixel_qa from LEDAPS Product Guide - 22 - Version 8.1
// 68, 132 = Water 
// 72, 136 =  Cloud shadow
// 80, 112, 144, 176 = Snow/ice
// 96, 112, 160, 176, 224 = Cloud


// select pixel_qa band as mask
var msk = cloudy_scene.select('pixel_qa');

//conditions which to mask out - no shadows, snow or clouds
msk = msk.neq(68).and(msk.neq(132))
      .and(msk.neq(72)).and(msk.neq(136))
       .and(msk.neq(80)).and(msk.neq(112)).and(msk.neq(144)).and(msk.neq(176))
        .and(msk.neq(96)).and(msk.neq(160)).and(msk.neq(176)).and(msk.neq(224));

// apply mask
var masked = cloudy_scene.mask(msk);

// add masked image to Layer
Map.addLayer(masked,{min:0,max:3000,bands:['B3','B2','B1']},'masked');

If one needs to apply an image mask over a collection use the map() function:

var rectangle = ee.Geometry.Rectangle(96.01669, 18.52621, 96.04819, 18.49634);
Map.centerObject(rectangle);

var bands = ['NDVI', 'SummaryQA'];

var modis = ee.ImageCollection("MODIS/006/MOD13Q1").filterDate('2000-01-01', '2018-01-01').select(bands).filterBounds(rectangle);

// PIXEL QUALITY MASKING
var maskQA = function(image) {
   var summaryqaband = image.select('SummaryQA')
     var mask = summaryqaband.neq(2).and(summaryqaband.neq(3))
        return image.updateMask(mask);
};

var goodqualdataset = modis.map(maskQA)

print(goodqualdataset);

// MAKE A LIST OF THE IMAGES IN THE COLLECTION
var goodquallistOfImages = goodqualdataset.toList(goodqualdataset.size());


// VISUALIZATION PARAMETERS
var ndviParams = {bands:['NDVI'], min: -1, max: 1, palette: ['blue', 'white', 'green']};

var img1 = goodquallistOfImages.get(0);

// ADD THE LAYER AND SEE HOW THE MASK WORKED
Map.addLayer(ee.Image(img1).divide(10000).clip(rectangle), ndviParams, 'masked-modis-image-2000-02-18')

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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