0

I am trying to follow this Tutorial but in a different country. I am currently having a problem with cloud masks. I tried to visualize the different cloud masks of different patches at different dates. Sometimes the masks over-estimate the cloud coverage like the following screenshot, but in this case, I think it classified clouds and cloud shadow as clouds (not sure though):

Cloud mask

But when it comes to small clouds they go undetected, which will most likely jeopardize later processing steps (crop type classification). Here is an example of that:

enter image description here enter image description here and this is the valid pixel count plot: This is the time interval : time_interval = ['2019-01-01', '2019-12-31']

These cloud masks are generated using s2cloudless (a machine learning algorithm trained on S2-L1C images). This is the code I used to download the images:

class SentinelHubValidData:
    """
    Combine Sen2Cor's classification map with `IS_DATA` to define a `VALID_DATA_SH` mask
    The SentinelHub's cloud mask is asumed to be found in eopatch.mask['CLM']
    """
    def __call__(self, eopatch):        
        return np.logical_and(eopatch.mask['IS_DATA'].astype(np.bool), 
                              np.logical_not(eopatch.mask['CLM'].astype(np.bool)))
    
class CountValid(EOTask):   
    """
    The task counts number of valid observations in time-series and stores the results in the timeless mask.
    """
    def __init__(self, count_what, feature_name):
        self.what = count_what
        self.name = feature_name
        
    def execute(self, eopatch):
        eopatch.add_feature(FeatureType.MASK_TIMELESS, self.name, np.count_nonzero(eopatch.mask[self.what],axis=0))
        
        return eopatch

# Correspond to [coastal aerosol, B, G, R, vegetation red edge1,vegetation red edge2,vegetation red edge3, NIR, vegetation red edge4, water vapor, SWIR1, SWIR2] wavelengths BANDS-S2-L2A
band_names=['B01','B02','B03','B04','B05','B06','B07','B08','B8A','B09','B11','B12']  

# TASK FOR BAND DATA and CLOUD MASK and CLOUD PROBABILITY
# add a request for S2 bands (downloading the data from the configurator)
# s2cloudless masks and probabilities are requested via additional data
add_data = SentinelHubInputTask(
    bands_feature=(FeatureType.DATA, 'BANDS'),
    bands = band_names,
    resolution=10,
    maxcc=0.1,
    time_difference=datetime.timedelta(minutes=120),
    data_source=DataSource.SENTINEL2_L2A,
    additional_data=[(FeatureType.MASK, 'dataMask', 'IS_DATA'),
                     (FeatureType.MASK, 'CLM'),
                     (FeatureType.DATA, 'CLP')])

# TASK FOR VALID MASK
# validate pixels using SentinelHub's cloud detection mask and region of acquisition 
add_sh_valmask = AddValidDataMaskTask(SentinelHubValidData(), 
                                      'VALID_DATA' # name of output mask
                                     )


# TASK FOR COUNTING VALID PIXELS
# count number of valid observations per pixel using valid data mask 
count_val_sh = CountValid('VALID_DATA', # name of existing mask
                          'VALID_COUNT' # name of output scalar
                         )

I found out that fmask is also used for cloud masking but I couldn't download the python package in google colab. So I want to know if there is any other way, using python, to mask those undetected small clouds.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.