0
# Cloud Masking
1
2
Specialized cloud and shadow masking for Landsat and Sentinel-2 imagery with configurable algorithms and thresholds. Geedim provides automatic detection of image collection types and applies appropriate masking methods.
3
4
## Capabilities
5
6
### Cloud Mask Methods
7
8
Enumeration of available cloud masking methods for Sentinel-2 imagery.
9
10
```python { .api }
11
class CloudMaskMethod(Enum):
12
"""Enumeration for Sentinel-2 cloud masking methods."""
13
14
cloud_prob = 'cloud-prob'
15
"""
16
Threshold the Sentinel-2 Cloud Probability.
17
18
Deprecated since version 1.9.0: Please use the cloud_score method.
19
"""
20
21
qa = 'qa'
22
"""
23
Bit mask the QA60 quality assessment band.
24
25
Deprecated since version 1.9.0: Please use the cloud_score method.
26
"""
27
28
cloud_score = 'cloud-score'
29
"""
30
Threshold the Sentinel-2 Cloud Score+.
31
32
Uses the GOOGLE_CLOUD_SCORE_PLUS_V1_S2_HARMONIZED dataset.
33
"""
34
```
35
36
### Cloud Score Bands
37
38
Enumeration for Sentinel-2 Cloud Score+ bands used with the cloud_score method.
39
40
```python { .api }
41
class CloudScoreBand(Enum):
42
"""Enumeration for Sentinel-2 Cloud Score+ bands."""
43
44
cs = 'cs'
45
"""
46
Pixel quality score based on spectral distance from a clear reference.
47
"""
48
49
cs_cdf = 'cs_cdf'
50
"""
51
Cumulative distribution function value of possible cs values.
52
"""
53
```
54
55
### Masking Parameters
56
57
Cloud masking parameters vary by image collection type:
58
59
#### Landsat Parameters
60
61
```python { .api }
62
def addMaskBands(
63
mask_cirrus: bool = True,
64
mask_shadows: bool = True,
65
**kwargs
66
) -> ee.Image:
67
"""
68
Add mask bands for Landsat imagery.
69
70
Parameters:
71
- mask_cirrus (bool): Whether to mask cirrus clouds (valid for Landsat 8-9)
72
- mask_shadows (bool): Whether to mask cloud shadows
73
- **kwargs: Additional masking parameters
74
"""
75
```
76
77
#### Sentinel-2 Parameters
78
79
```python { .api }
80
def addMaskBands(
81
method: CloudMaskMethod = CloudMaskMethod.cloud_score,
82
prob: float = 0.6,
83
cloud_dist: float = 1000.0,
84
band: CloudScoreBand = CloudScoreBand.cs_cdf,
85
**kwargs
86
) -> ee.Image:
87
"""
88
Add mask bands for Sentinel-2 imagery.
89
90
Parameters:
91
- method (CloudMaskMethod): Cloud masking method
92
- prob (float): Cloud probability threshold (0.0-1.0)
93
- cloud_dist (float): Maximum cloud distance in meters
94
- band (CloudScoreBand): Cloud Score+ band to use
95
- **kwargs: Additional masking parameters
96
"""
97
```
98
99
### Mask Band Types
100
101
Different mask bands are automatically added based on image type:
102
103
```python { .api }
104
# Common mask bands
105
FILL_MASK: ee.Image # Valid data mask
106
CLOUDLESS_MASK: ee.Image # Cloud-free pixels mask
107
CLOUD_DIST: ee.Image # Distance to nearest cloud (meters)
108
109
# Landsat-specific bands
110
QA_MASK: ee.Image # Quality assessment mask
111
SHADOW_MASK: ee.Image # Cloud shadow mask
112
CIRRUS_MASK: ee.Image # Cirrus cloud mask
113
114
# Sentinel-2 specific bands
115
CLOUD_PROB: ee.Image # Cloud probability (0-100)
116
CLOUD_SCORE: ee.Image # Cloud Score+ value
117
```
118
119
### Coverage Statistics
120
121
Calculate cloud coverage and fill statistics for regions:
122
123
```python { .api }
124
def set_mask_portions(
125
ee_image: ee.Image,
126
region: dict | ee.Geometry = None,
127
scale: float = None
128
) -> ee.Image:
129
"""
130
Set FILL_PORTION and CLOUDLESS_PORTION properties.
131
132
Parameters:
133
- ee_image (ee.Image): Image to analyze
134
- region (dict | ee.Geometry, optional): Analysis region
135
- scale (float, optional): Analysis scale in meters
136
137
Returns:
138
ee.Image: Image with portion properties set
139
"""
140
```
141
142
## Usage Examples
143
144
### Landsat Cloud Masking
145
146
```python
147
import ee
148
import geedim
149
150
geedim.Initialize()
151
152
# Load Landsat 8 image
153
image = ee.Image('LANDSAT/LC08/C02/T1_L2/LC08_173083_20200601')
154
155
# Add mask bands with custom parameters
156
masked_image = image.gd.addMaskBands(
157
mask_cirrus=True, # Mask cirrus clouds
158
mask_shadows=True # Mask cloud shadows
159
)
160
161
# Apply cloud masking
162
cloud_free = masked_image.maskClouds()
163
164
# Check cloud coverage
165
region = ee.Geometry.Point(-122.4194, 37.7749).buffer(10000)
166
coverage_image = masked_image.gd.set_mask_portions(region=region, scale=30)
167
168
# Get coverage statistics from image properties
169
fill_portion = coverage_image.get('FILL_PORTION').getInfo()
170
cloudless_portion = coverage_image.get('CLOUDLESS_PORTION').getInfo()
171
172
print(f"Fill portion: {fill_portion}%")
173
print(f"Cloudless portion: {cloudless_portion}%")
174
```
175
176
### Sentinel-2 Cloud Masking
177
178
```python
179
# Load Sentinel-2 image
180
s2_image = ee.Image('COPERNICUS/S2_SR_HARMONIZED/20200601T185751_20200601T185931_T10SEG')
181
182
# Add mask bands using Cloud Score+ method
183
masked_s2 = s2_image.gd.addMaskBands(
184
method=geedim.CloudMaskMethod.cloud_score,
185
prob=0.65, # 65% cloud probability threshold
186
cloud_dist=2000, # 2km maximum cloud distance
187
band=geedim.CloudScoreBand.cs_cdf # Use CDF band
188
)
189
190
# Apply cloud masking
191
cloud_free_s2 = masked_s2.maskClouds()
192
193
# Alternative: Use legacy methods (deprecated)
194
legacy_masked = s2_image.gd.addMaskBands(
195
method=geedim.CloudMaskMethod.qa, # QA60 band method
196
prob=0.6
197
)
198
```
199
200
### Collection-Wide Cloud Masking
201
202
```python
203
# Load image collection
204
collection = ee.ImageCollection('LANDSAT/LC08/C02/T1_L2') \
205
.filterDate('2020-01-01', '2020-12-31') \
206
.filterBounds(region)
207
208
# Add mask bands to entire collection
209
masked_collection = collection.gd.addMaskBands(
210
mask_cirrus=True,
211
mask_shadows=True
212
)
213
214
# Apply cloud masking to all images
215
cloud_free_collection = masked_collection.maskClouds()
216
217
# Filter by cloud coverage
218
low_cloud_collection = collection.gd.search(
219
start_date='2020-06-01',
220
end_date='2020-09-30',
221
cloudless_portion=80, # Minimum 80% cloud-free
222
fill_portion=95 # Minimum 95% valid data
223
)
224
```
225
226
### Advanced Masking Configuration
227
228
```python
229
# Custom cloud distance calculation
230
def custom_cloud_masking(image):
231
# Add mask bands with custom parameters
232
masked = image.gd.addMaskBands(
233
method=geedim.CloudMaskMethod.cloud_score,
234
prob=0.5, # Lower threshold for more aggressive masking
235
cloud_dist=5000, # 5km cloud buffer
236
band=geedim.CloudScoreBand.cs # Use raw cloud score
237
)
238
239
# Get cloud distance band for analysis
240
cloud_dist = masked.select('CLOUD_DIST')
241
242
# Apply masking
243
return masked.maskClouds()
244
245
# Apply to collection
246
custom_masked = collection.map(custom_cloud_masking)
247
```
248
249
### Mask Quality Assessment
250
251
```python
252
# Analyze mask quality for a region
253
def assess_mask_quality(image, region, scale=30):
254
# Add mask bands and calculate portions
255
masked = image.gd.addMaskBands().gd.set_mask_portions(
256
region=region,
257
scale=scale
258
)
259
260
# Extract mask statistics
261
stats = {
262
'image_id': image.get('system:id').getInfo(),
263
'fill_portion': masked.get('FILL_PORTION').getInfo(),
264
'cloudless_portion': masked.get('CLOUDLESS_PORTION').getInfo(),
265
'date': image.date().format('YYYY-MM-dd').getInfo()
266
}
267
268
return stats
269
270
# Assess collection
271
region = ee.Geometry.Rectangle([-122.5, 37.7, -122.3, 37.8])
272
collection_list = collection.limit(10).getInfo()['features']
273
274
quality_stats = []
275
for img_info in collection_list:
276
img = ee.Image(img_info['id'])
277
stats = assess_mask_quality(img, region)
278
quality_stats.append(stats)
279
280
# Print results
281
for stats in quality_stats:
282
print(f"{stats['date']}: {stats['cloudless_portion']:.1f}% cloud-free")
283
```