Masking Clouds and Shadows¶
Masking clouds and shadows may seem hard, but it isn’t! Let’s take a look on it!
Before anything, let’s import our modules and authenticate in Google Earth Engine:
import ee, eemont
ee.Authenticate()
ee.Initialize()
Now, we are ready to go!
Overview¶
The eemont package extends the ee.Image and ee.ImageCollection classes with the method maskClouds()
:
ee.Image¶
|
Masks clouds and shadows in an image (valid just for Surface Reflectance products). |
ee.ImageCollection¶
|
Masks clouds and shadows in an image collection (valid just for Surface Reflectance products). |
Supported Platforms¶
This method automatically masks clouds and shadows on the following supported satellite platforms:
Sentinel Missions¶
Landsat Missions¶
MODIS Products (Terra + Aqua)¶
MODIS Products (Terra)¶
MODIS Products (Aqua)¶
MYD09GA.006 Aqua Surface Reflectance Daily Global 1km and 500m
MYD17A2H.006: Aqua Gross Primary Productivity 8-Day Global 500M 500m
Warning
Not supported satellite platforms will raise an Exception.
QA Method¶
By default, the maskClouds()
uses the QA band of each paltform to compute the clouds and shadows masks (except for Sentinel-2, where the default method is Cloud Probability). The following table shows the band and the bits used for each platform (The value in parentheses is the valid value of the bitmask):
Platform |
QA Band |
Cloud Bitmask |
Cirrus Bitmask |
Shadow Bitmask |
---|---|---|---|---|
Sentinel-3 |
quality_flags |
27 (0) |
||
Sentinel-2 |
QA60 |
10 (0) |
11 (0) |
|
Landsat Series |
pixel_qa |
5 (0) |
3 (0) |
|
MOD09GA |
state_1km |
0 (0) |
8 (0) |
2 (0) |
MOD09Q1 |
State |
0 (0) |
8 (0) |
2 (0) |
MOD09A1 |
StateQA |
0 (0) |
8 (0) |
2 (0) |
MCD15A3H |
FparExtra_QC |
5 (0) |
4 (0) |
6 (0) |
MOD17A2H |
Psn_QC |
3 (0) |
||
MOD16A2 |
ET_QC |
3 (0) |
||
MOD13Q1 |
SummaryQA |
0 (0) |
||
MOD13A1 |
SummaryQA |
0 (0) |
Usage¶
Let’s check how to use the maskClouds()
method for different platforms:
Sentinel-3¶
On Sentinel 3, clouds are masked according to the bright pixels in the quality_flags band of the Sentinel-3 OLCI EFR: Ocean and Land Color Instrument Earth Observation Full Resolution.
Warning
This method may mask water as well on Sentinel-3 images.
Let’s take the Sentinel-3 image collection as example:
S3 = ee.ImageCollection('COPERNICUS/S3/OLCI')
There is no need to specify any arguments, since they’re ignored.
S3.maskClouds()
This method can also be applied to a single image:
S3.first().maskClouds()
And can be used for scaled images without specifying it:
S3.scale().maskClouds()
Sentinel-2¶
On Sentinel 2, clouds can be masked using two methods: QA and Cloud Probability. The QA method uses the QA60 band in the Surface Reflectance Product to mask clouds, while the Cloud Probability method uses the COPERNICUS/S2_CLOUD_PROBABILITY collection to do it.
Shadows are masked based on the clouds mask, where shadows are searched within a range from clouds edges in the shadows direction.
See also
For more info on masking shadows, please visit ‘Braaten, J. 2020. Sentinel-2 Cloud Masking with s2cloudless. Google Earth Engine, Community Tutorials’.
First, let’s take the Sentinel-2 image collection:
S2 = ee.ImageCollection('COPERNICUS/S2_SR')
In order to use the QA method, it must be specified using the method
parameter:
S2.maskClouds(method = 'qa')
This line maps the QA masking method over the whole collection, but the method can also be applied to a single image:
S2.first().maskClouds(method = 'qa')
The QA method gives us the option to avoid masking cirrus clouds, but it must be specified using the maskCirrus
parameter:
S2.maskClouds(method = 'qa', maskCirrus = False)
And we can also avoid masking shadows by specifying the maskShadows
parameter:
S2.maskClouds(method = 'qa', maskShadows = False)
Now, in order to use the Cloud Probability method, we can specify it in the method
parameter:
S2.maskClouds(method = 'cloud_prob')
But, it is the default method, so you can just let the extended method with no additional parameters:
S2.maskClouds()
The Cloud Probability method uses a probability threshold to mask clouds, by default, the threshold is set to 60, but it can be modified using the prob
parameter:
S2.maskClouds(prob = 70)
If your image or collection is scaled, the scaledImage
parameter must be set to True
:
S2.scale().maskClouds(scaledImage = True)
In order to search for shadows, portental shadow pixels must be specified. Pixels with a NIR reflectance below 0.15 are considered potential shadow pixels, but this can be modified using the
dark
parameter:
S2.maskClouds(dark = 0.2)
Shadows are searched whitin a maximum range of 1000 m in the shadow direction from cloud edges, but this range can be modified using the cloudDist
parameter:
S2.maskClouds(cloudDist = 1500)
After finding all clouds and shadows, the mask can be dilated to avoid border effects. By default, clouds and shadows are dilated by 250 m, but this can be modified using the buffer
parameter:
S2.maskClouds(buffer = 100)
Finally, in order to avoid confusion between clouds and bright surface objects, the Cloud Displacement Index (CDI) can be used. By default, the CDI is not used, but it can be modified
using the cdi
parameter:
S2.maskClouds(cdi = -0.5)
Landsat Series¶
On Landsat Series, both clouds and shadows are masked based on the pixel_qa band in the Surface Reflectance Products.
Let’s take the Landsat 8 image collection as example:
L8 = ee.ImageCollection('LANDSAT/LC08/C01/T1_SR')
There is no need to specify most of the arguments showed for Sentinel-2, since they’re ignored.
L8.maskClouds()
Shadows are masked by default, but if required, the maskShadows
parameter can be modified.
L8.maskClouds(maskShadows = False)
This method can also be applied to a single image:
L8.first().maskClouds()
And can be used for scaled images without specifying it:
L8.scale().maskClouds()
MODIS Products¶
On MODIS Products, clouds and shadows are masked according to the specific QA band.
Let’s take the MOD13Q1 image collection as example:
MOD13Q1 = ee.ImageCollection('MODIS/006/MOD13Q1')
There is no need to specify most of the arguments showed for Sentinel-2, since they’re ignored.
MOD13Q1.maskClouds()
MOD13Q1, MOD13A1, MOD17A2H and MOD16A2 products don’t have cirrus and shadow bitmasks, therefore, the arguments maskShadows
and maskCirrus
are ignored. MOD09GA, MOD09Q1, MOD09A1 and MCD15A3H products have cirrus and shadows bitmasks, and by default, they are set to True. If required, they can be set to False:
MOD09GA = ee.ImageCollection('MODIS/006/MOD09GA').maskClouds(maskShadows = False, maskCirrus = False)
This method can also be applied to a single image:
MOD09GA.first().maskClouds()
And can be used for scaled images without specifying it:
MOD09GA.scale().maskClouds()
MOD13A2 doesn’t have a bitmask QA band, instead, it has a Class QA band, where a value of zero means that the pixel has good data.
MOD13A2 = ee.ImageCollection('MODIS/006/MOD13A2').maskClouds()