I am a GEE and JavaScript novice.
I am trying to calculate a specific fire index for a collection of sentinel 2 images so as to map burn scars throughout a one year period. I then want to apply a mask on all the images when this particular index exceeds a certain value. Finally I want to combine this collection of masked images into a single image with a mask on any pixel that satisfied the threshold range for the burn index within the specified date range. This is where I am at in terms of initialising the process.
var sentinel2series = ee.ImageCollection(sentinel2.filterDate('2019-01-01', '2020-01-01').filterBounds(geometry).select('B12', 'B11', 'B8'));
print(sentinel2series)
// Function to calculate and add a MIRBI band
var addMIRBI = function(image) {
var MIRBI = image.expression(
'10*(SWIR2)-9.8*(SWIR1)+2', {
'SWIR2' : image.select('B12'),
'SWIR1' : image.select('B11')
})
.rename('MIRBI')
return image.addBands(MIRBI);
};
var serieswithBIndex = sentinel2series.map(addMIRBI)
print(serieswithBIndex)
I have tried various iterating functions on my images but haven't had much luck. The addition of the burn index band seems to work fine as when I view the collection each image has a new band titled 'MIRBI'. I just cannot get across the line with masking the images once they exceed a threshold for that value and then combining those masks into a singular image that is an aggregate of all the masks.
I have applied the process detailed below by Rodrigo Lustosa, and I have since tried to run the script there and it was displaying something like what I am looking for. However I know it's not quite right because there is a fire in particular that I am trying to capture and I know it's outline shape (ie. it's been groundtruthed and it is my way of QA) but it seemed to get obscured in the mask - probably by erroneous clouds I guessed.
I since applied a cloud mask to the ImageCollection after it had the MIRBI band appended to each image, and then did the same process as outlined below with using the Reducer to get the maximum MIRBI value for each pixel. However now the area where there should be a mask indicating fire (ie. where the groundtruthed fire is and I know there is a fire scar) there isn't a mask. Is it possible that something with my cloud masking has interfered with my subsequent masking of the MIRBI threshold?
Here's my working script
Map.centerObject(geometry);
var sentinel2series = ee.ImageCollection(sentinel2.filterDate('2019-01-01', '2020-01-01').filterBounds(geometry).select('B12', 'B11', 'B8', 'B4', 'B3', 'B2', 'QA60'));
print(sentinel2series)
// Function to calculate and add a MIRBI band
var addMIRBI = function(image) {
var MIRBI = image.expression(
'(10*SWIR2)-(9.8*SWIR1)+2', {
'SWIR2' : image.select('B12'),
'SWIR1' : image.select('B11')
})
.rename('MIRBI')
return image.addBands(MIRBI);
};
var serieswithMIRBI = sentinel2series.map(addMIRBI)
print(serieswithMIRBI)
function maskS2sr(image) {
var cloudShadowBitMask = (2<<10);
var cloudsBitMask = (2<<11);
// Get the pixel QA band.
var qa = image.select('QA60');
// Both flags should be set to zero, indicating clear conditions.
var mask = qa.bitwiseAnd(cloudShadowBitMask).eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
return image.updateMask(mask);
}
// mask clouds and cirrus
var seriesNoClouds = serieswithMIRBI.map(maskS2sr);
var certainValue = -5000;
var othervalue = 0;
// get max value for each pixel
var final_image = seriesNoClouds.select('MIRBI')
.reduce(ee.Reducer.max());
// mask every pixel which was greater than certainValue in any image
var final_image_masked = final_image
.updateMask(final_image.gt(certainValue).and(final_image.lt(othervalue)));
// view example on the map
Map.addLayer(final_image_masked,{},'max MIRBI masked');
print(final_image_masked)
I am reasonably confident in my threshold values, at least for the ROI that I am looking where I have validated them with a fire scar that I know is there in that image series.