2

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(???

1 Answer 1

10

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

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.