MODIS cloud masking

Create a cloud free MODIS composite

 

Use the code below or follow this link.


// import data
var collection = ee.ImageCollection("MODIS/MOD09A1")

// Define dates
var iniDate = ee.Date.fromYMD(2010,1,1);
var endDate = ee.Date.fromYMD(2010,1,31);

// bands
var modisBands = ['sur_refl_b03','sur_refl_b04','sur_refl_b01','sur_refl_b02','sur_refl_b06','sur_refl_b07'];
var lsBands = ['blue','green','red','nir','swir1','swir2'];

// helper function to extract the QA bits
function getQABits(image, start, end, newName) {
 // Compute the bits we need to extract.
 var pattern = 0;
 for (var i = start; i <= end; i++) {
 pattern += Math.pow(2, i);
 }
 // Return a single band image of the extracted QA bits, giving the band
 // a new name.
 return image.select([0], [newName])
 .bitwiseAnd(pattern)
 .rightShift(start);
}

// A function to mask out cloudy pixels.
function maskQuality(image) {
 // Select the QA band.
 var QA = image.select('StateQA');
 // Get the internal_cloud_algorithm_flag bit.
 var internalQuality = getQABits(QA,8, 13, 'internal_quality_flag');
 // Return an image masking out cloudy areas.
 return image.updateMask(internalQuality.eq(0));
}

// create cloud free composite
var noCloud = collection.filterDate(iniDate,endDate)
 .map(maskQuality)
 .select(modisBands,lsBands);

// create composite with clouds
var Cloud = collection.filterDate(iniDate,endDate)
 .select(modisBands,lsBands);

// vis parameters
var visParams = {bands:['red','green','blue'],min:0,max:3000,gamma:1.3};

// add the cloud free composite
Map.addLayer(noCloud.median(),visParams,'MODIS Composite');

// add the cloud composite
Map.addLayer(Cloud.median(),visParams,'MODIS Composite clouds');

 

Advertisements

2 comments

  1. Hi there, thank you for this very helpful tutorial!

    I am new to Google Earth Engine and JavaScript for that matter, so am therefore trying to understand the method and functions you use a bit better. Two questions:
    1) Why is the mask created from pixels where internalQuality= 0? It is my understanding that the highest quality, least cloudy images will have bits equal to zero therefore when the .bitwiseAnd(pattern) is performed, it is only pixels equal to 0 that you want to keep. I am clearly misunderstanding something however as your code does remove clouds. Could you possible explain how the both the .bitwiseAnd(pattern) and also .rightShift(Start) work in this application?

    2) I’ve noticed that in regions not masked by the function there can still be a different shade to the resultant image, the result of different values for red/green/blue in the noCloud layer. I can’t figure out a pattern to the change in values however. I would think that as this is a cloud mask, only pixels with clouds will be altered while those without will be left with the same values as before in all bands. Can you explain what is occurring here? Some regions values do remain the same as well.

    I hope these questions are not too rudimentary. I’m trying to understand this method in hopes of applying to different bits in both QA and State QA bands.

    Thank you for any input you can offer.

    Like

  2. I added a new post with the bitmask. hope that helps answering your question.

    The difference in color is caused by the median function at the end. for the no cloud image the median is taken from the cloud free imagecollection.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s