1

I have been working on cloud masking of the sentinel-2 data and need to calculate the null percentage of the given image for documentation purposes. I have been working using Python API. My code till now is -

s2Sr = ee.ImageCollection('COPERNICUS/S2_SR')

s2Clouds = ee.ImageCollection('COPERNICUS/S2_CLOUD_PROBABILITY')

COUNTRY_NAME = 'Malawi'

AOI = (ee.FeatureCollection("USDOS/LSIB_SIMPLE/2017").
   filter(ee.Filter.eq('country_na', COUNTRY_NAME)).geometry())

START_DATE = ee.Date('2020-01-01')
END_DATE = ee.Date('2020-12-31')
MAX_CLOUD_PROBABILITY = 30   

def mask_clouds(img):
   clouds = ee.Image(img.get('cloud_mask')).select('probability')
   is_not_cloud = clouds.lt(MAX_CLOUD_PROBABILITY)
   return img.updateMask(is_not_cloud)

def mask_edges(s2_img):
      return s2_img.updateMask(s2_img.select('B8A').mask().updateMask(s2_img.select('B9').mask()))

 criteria = ee.Filter.And(ee.Filter.bounds(AOI),
                     ee.Filter.date(START_DATE, END_DATE))

 s2Sr = s2Sr.filter(criteria).map(mask_edges)
 s2Clouds = s2Clouds.filter(criteria)

 s2SrWithCloudMask = ee.Join.saveFirst('cloud_mask').apply(**{
       'primary': s2Sr,
       'secondary': s2Clouds,
       'condition': ee.Filter.equals(**{
       'leftField': 'system:index',
       'rightField': 'system:index'
   })
 })

 s2CloudMasked = ee.ImageCollection(s2SrWithCloudMask).map(mask_clouds)

 s2_image = s2CloudMasked.median()

s2_median is the final image that I have. Now, I want to get the percentage of the area that has been masked by the cloud, i.e., there is no value for those pixels. I know how to get the total number of pixels, but not the null pixels. I am getting total pixels using

  total_pixels = ee.Image.pixelArea().reduceRegion(**{
        'reducer': ee.Reducer.count(),
        'geometry': AOI,
        'scale': 30,
        'maxPixels': 1e19
  }).getInfo()['area']
  

1 Answer 1

3

You can extract the mask from your masked image with ee.Image.mask(). Use that one to determine which pixels to include when you're calculating the area. I'm having a multi-band image, and there's a mask for each band. I'm consider a pixel masked if any band is masked. The total area is picked up from the geometry in this case. This is in JavaScript, but it should be easy enough for you to turn this into Python.

var maskedOut = masked.mask().reduce(ee.Reducer.min()).not()
var maskedArea = ee.Image.pixelArea()
    .updateMask(maskedOut)
    .reduceRegion({
      reducer: ee.Reducer.sum(), 
      geometry: image.geometry(), 
      scale: 10, 
      maxPixels: 1e13
    })
    .getNumber('area')
var totalArea = image.geometry().area(10)
var percentageMasked = maskedArea.divide(totalArea).multiply(100)

https://code.earthengine.google.com/b6fc543157ddca0fdb21f419d66f61aa

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.