How can I mask clouds in a MODIS\MOD09A1 images in GEE? I know I should do sth with the "Bitmask for QA", but how?
var myImgCln = ee.ImageCollection("MODIS/006/MOD09A1")
.filterMetadata(???
I haven't actually worked with MODIS, but it looks like most other image collections in EE. The images contains a QA band, StateQA
, with data about clouds/shadow/etc. The catalog contains a description of which bits contains which information:
Bits 0-1: Cloud state 0: Clear 1: Cloudy 2: Mixed 3: Not set, assumed clear Bit 2: Cloud shadow 0: No 1: Yes Bits 3-5: Land/water flag 0: Shallow ocean 1: Land 2: Ocean coastlines and lake shorelines 3: Shallow inland water 4: Ephemeral water 5: Deep inland water 6: Continental/moderate ocean 7: Deep ocean Bits 6-7: Aerosol quantity 0: Climatology 1: Low 2: Average 3: High Bits 8-9: Cirrus detected 0: None 1: Small 2: Average 3: High Bit 10: Internal cloud algorithm flag 0: No cloud 1: Cloud Bit 11: Internal fire algorithm flag 0: No fire 1: Fire Bit 12: MOD35 snow/ice flag 0: No 1: Yes Bit 13: Pixel is adjacent to cloud 0: No 1: Yes Bit 14: BRDF correction performed data 0: No 1: Yes Bit 15: Internal snow mask 0: No snow 1: Snow
The below code uses a little utility function to extract the values for a range of bits. A mask with "Deep inland water" would be bitwiseExtract(image, 3, 5).eq(5)
.
var image = ee.ImageCollection("MODIS/006/MOD09A1").first()
var qa = image.select('StateQA')
var cloudState = bitwiseExtract(qa, 0, 1)
var cloudShadowState = bitwiseExtract(qa, 2)
var cirrusState = bitwiseExtract(qa, 8, 9)
var mask = cloudState.eq(0) // Clear
.and(cloudShadowState.eq(0)) // No cloud shadow
.and(cirrusState.eq(0)) // No cirrus
var maskedImage = image.updateMask(mask)
Map.addLayer(image, {min: 0, max: 6000}, 'unmasked', false)
Map.addLayer(maskedImage, {min: 0, max: 6000}, 'masked')
/**
* Utility to extract bitmask values.
* Look up the bit-ranges in the catalog.
*
* value - ee.Number or ee.Image to extract from.
* fromBit - int or ee.Number with the first bit.
* toBit - int or ee.Number with the last bit (inclusive).
* Defaults to fromBit.
*/
function bitwiseExtract(value, fromBit, toBit) {
if (toBit === undefined) toBit = fromBit
var maskSize = ee.Number(1).add(toBit).subtract(fromBit)
var mask = ee.Number(1).leftShift(maskSize).subtract(1)
return value.rightShift(fromBit).bitwiseAnd(mask)
}
https://code.earthengine.google.com/06804ee80db139b931c2aa6329fa4c8b