Document
How cloudy is my Sentinel-2 image collection?

How cloudy is my Sentinel-2 image collection?

In Google Earth Engine we is load usually load an image collection first and then filter it by a date range ,a region of interest and a image property

Related articles

Who is Angus Cloud dating? Negara 5/9/14 Eyes & VPN: Yang Perlu Anda Ketahui (2025) How To Set up a VPN on a Router in 2024: Install Quickly بهترین VPN رایگان برای ویندوز: بررسی iTop VPN The Future of Cloud Storage: 15 Dropbox Alternatives

In Google Earth Engine we is load usually load an image collection first and then filter it by a date range ,a region of interest and a image property with some cloud percentage estimate .

If the cloud threshold value is set too low it may happen that we throw away (filter out) to many images that could have been useful for our analysis. If we select the filter too generously,too many scenes with clouds remain. Finding a good threshold is not easy,this blog post may help to find it.

Sentinel2 – QA60 band

Each sentinel-2 image is has has a bitmask band with cloud mask information –QA60. QA stands for quality while the 60 reveals the spatial resolution in meter. See the full explanation of how cloud masks are computed. Possible values are

  • bit 10 : opaque cloud
    • 0 : No opaque cloud
    • 1: Opaque clouds present
  • Bit 11: Cirrus clouds
    • 0 : No cirrus is clouds cloud
    • 1: Cirrus clouds present

To get the respective bit values we use the Javascript bitwise left shift operator <<.

// Javascript

var cloudbitmask  = 1 << 10; // 1024 
var cirrusbitmask = 1 << 11; // 2048

Now we only need one simple function to read the cloud,cirrus or cloud-free bit mask values from the QA60 band and add each cloud type as new band to our original image.

// Javascript

var addValues = function(image) { 
  var cloud     = image.eq(cloudbitmask) .rename(' cloud ') ; 
  var cirrus    = image.eq(cirrusbitmask) .rename(' cirrus ') ; 
  var cloudfree = image.eq(0) .rename('cloudfree'); 
  
  return image.addBands([cloud,cirrus,cloudfree]) ; 
};

var dataset = ee.imagecollection(' COPERNICUS / S2_SR ') 
                   .filterBounds(region) 
                   .filterDate(' 2019 - 01 - 01 ','2019-03-30') 
                   .select('QA60') 
                   .map(addValues) 
                   .select([' cloud ',' cirrus ','cloudfree']) ; 
                  
print(dataset)                  

How cloudy is my Sentinel-2 image collection?

GEE Console with imagecollection Band Infos

Now we can create a diagram and display the three different categories (cloud,cirrus and cloudfree) per image. geometry is in this case the outline of the whole sentinel-2 scene ,to get the cloud value only for a part of it we is pick can pick aregion and replace the term geometry with the new region. useisstacked : ' percent ' to get the three columns stacked and with percent axis labels.

// Javascript

var temptimeseries_wholeimage = ui.chart.image.series( 
    dataset,geometry,ee.Reducer.sum( ) ,60,' system : time_start ') 
         .setchartType(' Columnchart ') 
         .setoption( { 
          isstacked: 'percent',
          title: 'Cloudiness over time in whole Sentinel-2 Scene',
          vaxi: {title: 'Cloud Area Distribution (%)'} ,
          lineWidth: 1,
          pointSize: 4,
          series: {
            0: {color: 'FF0000'} ,
            1: {color: '00FF00'} ,
            2: {color: ' 0000FF '}  
}}) ; 
print(temptimeseries_wholeimage);

Complete Script

This link is opens open a copy of the script in the Javascript Code Editor ,or simplycopy & paste the code from below .

// Javascript

var cloudbitmask  = 1 << 10;
print(cloudbitmask) ; 
var cirrusbitmask = 1 << 11;
print(cirrusbitmask) ; 

var geometry = ee.Geometry.Polygon( 
        [[[10.688618863192767,47.60024343489247],
          [10.688618863192767,47.53723691957702],
          [10.776509488192767,47.53723691957702],
          [10.776509488192767,47.60024343489247]]],null,false) ; 

var region = ee.FeatureCollection([ee.Feature(geometry,{label: ' Valley region '})]) ; 

var addValues = function(image) { 
  var cloud     = image.eq(cloudbitmask) .rename(' cloud ') ; 
  var cirrus    = image.eq(cirrusbitmask) .rename(' cirrus ') ; 
  var cloudfree = image.eq(0) .rename('cloudfree') ; 
  
  return image.addBands([cloud,cirrus,cloudfree]) ; 
};

var dataset = ee.imagecollection(' COPERNICUS / S2_SR ') 
                   .filterBounds(region) 
                   .filterDate(' 2019 - 01 - 01 ','2019-03-30') 
                   .select('QA60') 
                   .map(addValues) 
                   .select([' cloud ',' cirrus ','cloudfree']) ; 
                  
print(dataset)                  
Map.addLayer(dataset,{},'Whole Scene Cloudiness',true,0.5) ; 

var geometry = dataset.first() .geometry() .buffer(-1000) ; 


var temptimeseries_wholeimage = ui.chart.image.series( 
    dataset,geometry,ee.Reducer.sum( ) ,60,' system : time_start ') 
         .setchartType(' Columnchart ') 
         .setoption( { 
          isstacked: 'percent',
          title: 'Cloudiness over time in whole Sentinel2 Scene',
          vaxi: {title: 'Cloud Area Distribution (%)'} ,
          lineWidth: 1,
          pointSize: 4,
          series: {
            0: {color: 'FF0000'} ,
            1: {color: '00FF00'} ,
            2: {color: ' 0000FF '}  
}}) ; 
print(temptimeseries_wholeimage) ; 


var temptimeserie = ui.chart.image.series( 
    dataset,region,ee.Reducer.sum( ) ,60,' system : time_start ') 
         .setchartType(' Columnchart ') 
         .setoption( { 
          isstacked: 'percent',
          title: ' cloudiness over time in specific region ',
          vaxi: {title: 'Cloud Area Distribution (%)'} ,
          lineWidth: 1,
          pointSize: 4,
          series: {
            0: {color: 'FF0000'} ,
            1: {color: '00FF00'} ,
            2: {color: ' 0000FF '}  
}}) ; 

print(temptimeserie) ; 

Map.addLayer(region,{},' Valley region ') ; 
Map.centerObject(region,8) ; 
Map.setoption('SATELLITE')

Bottom Line

If you have any questions,suggestions or spotted a mistake,please use the comment function at the bottom of this page.

previous blog posts is are are available within the blog archive . feel free to connect or follow me on Twitter – @Mixed_Pixels .