I have a cloud masked Landsat 7 image collection. For each image I want to unmask the bands with their respective mean value.
This works fine, unless an image is completely cloud masked and therefore contains no data.
I tried adapting this related answer (in JavaScript) to my needs
start_date = "2018-01-01"
end_date = "2021-12-31"
l7 = (ee.ImageCollection("LANDSAT/LE07/C02/T1_L2")
.filterDate(ee.Date(start_date), ee.Date(end_date))
.filterBounds(aoi)
.map(lambda image: image.clip(aoi))
)
band_names = ['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B5', 'SR_B7', 'QA_PIXEL']
## fn.cloudmask_LS is a wrapper for a cloud masking procedure similar to this: https://gis.stackexchange.com/q/405056/128665
l7 = l7.select(band_names).map(fn.cloudmask_LS('QA_PIXEL'))
## drop QA_PIXEL band
band_names = [b for b in band_names if not b == 'QA_PIXEL']
l7 = l7.select(band_names)
################################################
## function adapted from the other GIS SE answer
################################################
def mask_with_mean(image):
time = image.get("system:time_start")
meanDict = image.reduceRegion(reducer=ee.Reducer.mean(), geometry=aoi)
outImg = ee.Image(ee.Algorithms.If(
meanDict.values(),
image.unmask(ee.Image.constant(meanDict.values(band_names))),
ee.Image(0).selfMask().set('isNull', True)
))
return outImg.set({"system:time_start":time})
## True is an attempt to get the map function to drop nulls but it doesn't appear to be working.
l7 = l7.map(mask_with_mean, True)
But I receive the following error:
ee.ee_exception.EEException: Error in map(ID=LE07_169068_20180128): Image.constant: Invalid type for constant image value.
Expected type: Number or Array.
Actual type: Object.
Actual value: null
I have tried meanDict
in the ee.Algorithm.if
true clause also.
I believe the problem arises because meanDict
is null
for an empty image but I don't know how to catch that with the ee.Algorithm.if
.