How can I apply cloud masking to mndwi image in Earth Engine? - google-earth-engine

I want to apply cloud masking to a MDNWI image but I get the error message "s2SR.map is not a function". I don't know how to resolve it.
var geometry=ee.Geometry.Polygon([[41.55427215633343,41.57962485896675],
[41.607143860434995,41.57962485896675],
[41.607143860434995,41.62429558047125],
[41.55427215633343,41.62429558047125],
[41.55427215633343,41.57962485896675]]);
var s2SR = ee.ImageCollection('COPERNICUS/S2_SR')
//filter start and end date
.filter(ee.Filter.calendarRange(2018,2018,'year'))
.filter(ee.Filter.calendarRange(9,10,'month'))
//filter according to drawn boundary
.filterBounds(geometry)
.filterMetadata('CLOUD_COVERAGE_ASSESSMENT', 'less_than',1)
.mean();
//print(typeof(s2SR))
//print("s2SR", s2SR);
//Map.addLayer(s2SR, {bands: ['B4', 'B3', 'B2'], min: 0, max: 2000}, 'Sentinel ');
Map.centerObject(geometry,10)
var Green = s2SR.select("B3");
var SWIR = s2SR.select("B11");
var mndwi = Green.subtract(SWIR).divide(Green.add(SWIR)).rename('MNDWI');
//Map.addLayer(mndwi, {min:0, max:1}, 'mndwı');
///// Cloud
var S2maskedVeg = function(image) {
var MNDWI = image.select(['MNDWI']);
return image.addBands(ee.Image(1).updateMask(mndwi.gte(0.95)).rename('MNDVI_mask'));
};
var S2collection = s2SR.map(mndwi).map(S2maskedVeg)
Map.addLayer(S2collection,{}, 'S2 NDWI mask');
(https://code.earthengine.google.com/6835ca74e985d40df906681039358ee1)

Here, you already calculate the MNDWI over the whole collection:
var mndwi = Green.subtract(SWIR).divide(Green.add(SWIR)).rename('MNDWI');
Therefore, this line does not make much sense:
var S2collection = s2SR.map(mndwi).map(S2maskedVeg)
map() requires a function as input, but it is an ImageCollection. You can just skip this part and map your S2maskedVeg() function over mndwi directly:
var S2collection = mndwi.map(S2maskedVeg)

Related

Converting Aster L1T data radiance to surface reflectance in Google Earth Engine

I am working with ASTER images and I am trying to convert radiance values to reflectance. Currently, I converted DN values to radiance and I don't know what else to do. Also, I found a Landsat function, but I don't know if it works for this case. This is my code:
var AOI = ee.Geometry.Polygon([
[-75.01530862531565,9.762481145514606],[-74.58134866437815,9.762481145514606],
[-74.58134866437815,10.27637106477599],[-75.01530862531565,10.27637106477599]]);
var dataset = ee.ImageCollection('ASTER/AST_L1T_003')
.filter(ee.Filter.date('2000-01-01', '2020-10-30'))
.filterBounds(AOI)
.filterMetadata('CLOUDCOVER', 'less_than', 1)
.filter(ee.Filter.and(
ee.Filter.notNull(['GAIN_COEFFICIENT_B01']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B02']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B3N']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B04']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B05']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B06']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B07']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B08']),
ee.Filter.notNull(['GAIN_COEFFICIENT_B09'])));
print(dataset)
// red and NIR channel digital numbers to at sensor radiance
function bands (img) {
var gainB1 = 0.676;
var gainB2= 0.708;
var gainB3N = 0.862;
var gainB4= 0.2174;
var gainB5 = 0.0696;
var gainB6= 0.0625;
var gainB7 = 0.0597;
var gainB8= 0.0417;
var gainB9 = 0.0318;
var rad_b1 = (img.select('B01').subtract(1)).multiply(gainB1);
var rad_b2 = (img.select('B02').subtract(1)).multiply(gainB2);
var rad_b3 = (img.select('B3N') .subtract(1)).multiply(gainB3N);
var rad_b4 = (img.select('B04').subtract(1)).multiply(gainB4);
var rad_b5 = (img.select('B05') .subtract(1)).multiply(gainB5);
var rad_b6 = (img.select('B06').subtract(1)).multiply(gainB6);
var rad_b7 = (img.select('B07').subtract(1)).multiply(gainB7);
var rad_b8 = (img.select('B08').subtract(1)).multiply(gainB8);
var rad_b9 = (img.select('B09').subtract(1)).multiply(gainB9);
return (rad_b1).addBands(rad_b2).addBands(rad_b3).addBands(rad_b4)
.addBands(rad_b5).addBands(rad_b6).addBands(rad_b7)
.addBands(rad_b8).addBands(rad_b9);
}
// add all selected bands with radiance values
var rad_bands =dataset.map(bands)
print(rad_bands)
function copyProps(index){
var source = ee.Image(dataset.toList(dataset.size()).get(index))
var dest = ee.Image(rad_bands.toList(rad_bands.size()).get(index))
var image = ee.Image(dest.copyProperties(source))
return image
}
var seq = ee.List.sequence(0, rad_bands.size().subtract(1))
print(seq)
var final_col = ee.ImageCollection(seq.map(copyProps))
https://code.earthengine.google.com/5b2dfc9b609ba5738be49ae2915d3980

computing the math formula on the mask (google earth engine)

I am about to calculate Chorophyll-a in the water bodies in one region, as I outlined above. I have created a mask, with water=1, land=0(transparent). And I want to calculate quality formula (NDCI, refer to normalized difference chl-a index) over the mask I created in the last step. Here are my code.
function maskS2clouds(image) {
var qa = image.select('QA60')
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
var mask = qa.bitwiseAnd(cloudBitMask).eq(0).and(
qa.bitwiseAnd(cirrusBitMask).eq(0))
return image.updateMask(mask).divide(10000)
.select("B.*")
.copyProperties(image, ["system:time_start"])
}
var tiles = ['29UNV']
var collection = ee.ImageCollection("COPERNICUS/S2_SR")
.filterDate('2020-01-01', '2020-12-31')
.filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20))
.filter(ee.Filter.inList('MGRS_TILE', tiles))
print(collection)
var minmin = collection.map(maskS2clouds)
print(minmin)
var calndwi = function(image){
//water mask
var NDWI = image.normalizedDifference(['B3', 'B8']).rename('NDWI');
return image.addBands(NDWI).updateMask(NDWI.gt(0));
};
print(minmin.map(calndwi));
//Add NDWI to the clipped image collection
var withNDWI = minmin.map(calndwi).select('NDWI');
print("NDWI collection", withNDWI);
var bb = withNDWI.first();
Map.addLayer(bb,{},'ss');
var addNDCI = function(image) {
var ndci = image.normalizedDifference(['B5', 'B4']).rename('NDCI');
return image.addBands(ndci);
};
var withNDCI = minmin.map(addNDCI).select('NDCI');
print("NDCI collection", withNDCI);
var MASK = function(image) {
var mask = bb.mask(image);
return image.addBands(mask);
};
var maskk = withNDCI.map(MASK).select('mask');
print(maskk)**
and it give me the bug like ImageCollection (Error)
Error in map(ID=20200106T114451_20200106T114531_T29UNV):Image.select: Pattern 'mask' did not match any bands.what should I do? thanks a million
The maskk object does not contain any bands named mask, because your MASK function does not create or add any bands with that name.
What your code does, as you've currently written it, is this:
var MASK = function(image) {
// Apply a mask over the 'bb' image.
var mask = bb.mask(image);
// return 'image' (which was the 'mask' parameter above),
// with ALL bands from the object 'mask', which is now a 'masked' version of bb.
// since mask = bb.mask(image), all the bands from bb will be added.
return image.addBands(mask);
};
var maskk = withNDCI
// Map the 'MASK' function over the 'withNDCI' collection
.map(MASK)
// Attempt to select a band named 'mask' (which does not exist).
.select('mask');
I'm not sure what you're looking for when you try to select the mask 'band' - I assume what you want is the masked NCDI image. That's essentially what you have already - but the band names of the 'maskk' object are "NDWI" and "NDCI", since it is derived from the bb, and those are the bands that bb contains. There is no band named "mask".

consider the values for all pixels in a polygon in google earth engine

I calculated the MNDWI value of the picture collection
function MNDWI(image) {
var mndwi = image.normalizedDifference(['SR_B6', 'SR_B3']).rename('mndwi');
return image.addBands(mndwi);
}
// display MNDWI layer
var withMndwi = filtered.map(MNDWI);
var composite = withMndwi.median().clip(polygon);
var MndwiComposite = composite.select('mndwi');
I also use statistic to calculate the threshold
var chart = ui.Chart.image.seriesByRegion({
imageCollection: withMndwi,
regions: pol,
band: 'mndwi',
reducer:ee.Reducer.mean(),
scale:10, });
Now I want to consider every single value of the image collection, I did try something as recommendation in this [post][1] like:
function masking (image){
var sample = image.sample();
var threshold = sample.gte(chart); // gte = greater (gt) + equal (eq)
var mask = threshold.updateMask(threshold);
return image.updateMask(mask);
}
But it notices that: sample.gte is not a function
What should I do for now?
[1]: extract the values for all pixels in a polygon in google earth engine

How do I solve the 0 element problem in Google Earth Engine?

I used the .combine command to convert two image collections into a two-band image collection (in the last line) to use in a function in the next step. This command is executed but writes 0 elements in the console. Where does this problem come from?
code link: https://code.earthengine.google.com/ed0992093ff830d926c7dd14403477c6
Code:
var ndvi = function(img){
var bands = img.select(['B2','B3','B4','B8']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['B8','B4']).rename('NDVI_S2');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
var S2 = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
//.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE',20))
.map(ndvi);
print(S2);
var START = '2018-10-24';
var END = '2019-06-30';
var DATES = [ '2018-12-19', '2018-12-29', '2019-01-23', '2019-02-12', '2019-03-04',
'2019-03-19', '2019-04-08', '2019-04-13', '2019-05-13', '2019-05-18', '2019-05-23',
'2019-05-28', '2019-06-02', '2019-06-07', '2019-06-12', '2019-06-17', '2019-06-22',
'2019-06-27'];
var addTime = function(x) {
return x.set('Date', ee.Date(x.get('system:time_start')).format("YYYY-MM-dd"))};
var Sentinel = ee.ImageCollection(S2)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print(Sentinel);
var PMODIS =
ee.Image('MODIS/006/MCD43A4/2018_12_19').select('Nadir_Reflectance_Band4');
var MODProjection = PMODIS.projection();
print('MODIS projection:', MODProjection);
var Viz = {min: 0, max: 1, palette: ['be6c44','ca3a3a','e4ae0c','565c04','819536']};
var S2_resampled = Sentinel.map(function(img){
var S2Mean = img
// Force the next reprojection to aggregate instead of resampling.
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 2146
})
// Request the data at the scale and projection of the Sentinel image.
.reproject({
crs: MODProjection
});
return S2Mean
.copyProperties(img,['system:time_start','system:time_end','system:index']);
});
Map.addLayer(S2_resampled)
var M_ndvi = function(img){
var bands =
img.select(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).multiply(0.0001)
.clip(geometry);
var index=bands
.normalizedDifference(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5'])
.rename(
'NDVI_MOD');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
var MOD = ee.ImageCollection('MODIS/006/MCD43A4')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
.map(M_ndvi);
var MODIS = ee.ImageCollection(MOD)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print(MODIS);
var S2_and_MOD = S2_resampled.combine(MODIS, false);
print(S2_and_MOD);
var Diff = S2_and_MOD.map(function(img){
var clip = img.clip(geometry);
var Diffe = clip.expression('NDVI_S2 - NDVI_MOD',
{'NDVI_S2':clip.select('NDVI_S2') ,
'NDVI_MOD':clip.select('NDVI_MOD')}).rename('Diff');
return Diffe
.copyProperties(img,['system:time_start','system:time_end']); });
print(Diff);
ee.Image.combine() uses the system:ID property to join the 2 images. See the documentation here. Since your images do not match, the resulting collection has no images.
A solution that should fit your needs utilizes the ee.Join.inner() to take advantage of the Date property that you have created to join the 2 image collections. A similar question was answered here.
Using inner join, I was able to accomplish what appeared to be your goal of finding the difference in NDVI between the S2 and MODIS collections. The full working script can be found here: https://code.earthengine.google.com/dc45df1b7cf83723d53e9f7917975e2d
Code:
// Function - Calculate S2 NDVI
var ndvi = function(img){
var bands = img.select(['B2','B3','B4','B8']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['B8','B4']).rename('NDVI_S2');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
// Get S2 NDVI images
var S2 = ee.ImageCollection('COPERNICUS/S2_SR')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
//.filter(ee.Filter.lte('CLOUDY_PIXEL_PERCENTAGE',20))
.map(ndvi);
print('S2 NDVI ImageCollection',S2);
// Set Date Parameters
var START = '2018-10-24';
var END = '2019-06-30';
// Create Date List
var DATES = [ '2018-12-19', '2018-12-29', '2019-01-23', '2019-02-12', '2019-03-04',
'2019-03-19', '2019-04-08', '2019-04-13', '2019-05-13', '2019-05-18', '2019-05-23',
'2019-05-28', '2019-06-02', '2019-06-07', '2019-06-12', '2019-06-17', '2019-06-22',
'2019-06-27'];
// Function - Add 'Date' field to image
var addTime = function(x) {
return x.set('Date', ee.Date(x.get('system:time_start')).format("YYYY-MM-dd"))};
// Run addTime on S2 ImageCollection
var Sentinel = ee.ImageCollection(S2)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print('Date Added S2', Sentinel);
// Get MODIS Projection
var PMODIS = ee.Image('MODIS/006/MCD43A4/2018_12_19').select('Nadir_Reflectance_Band4');
var MODProjection = PMODIS.projection();
print('MODIS projection:', MODProjection);
// Set Visualization Parameters
var Viz = {min: 0, max: 1, palette: ['be6c44','ca3a3a','e4ae0c','565c04','819536']};
// Reproject S2 images to MODIS projection
var S2_resampled = Sentinel.map(function(img){
var S2Mean = img
// Force the next reprojection to aggregate instead of resampling.
.reduceResolution({
reducer: ee.Reducer.mean(),
maxPixels: 2146
})
// Request the data at the scale and projection of the Sentinel image.
.reproject({
crs: MODProjection
});
return S2Mean
.copyProperties(img,['system:time_start','system:time_end','system:index']);
});
print('S2_resampled',S2_resampled);
Map.addLayer(S2_resampled);
// Function - Calculate MODIS NDVI
var M_ndvi = function(img){
var bands = img.select(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).multiply(0.0001)
.clip(geometry);
var index = bands.normalizedDifference(['Nadir_Reflectance_Band1','Nadir_Reflectance_Band5']).rename('NDVI_MOD');
return index
.copyProperties(img,['system:time_start','system:time_end','system:index']);
};
// Get MODIS NDVI Images
var MOD = ee.ImageCollection('MODIS/006/MCD43A4')
.filterBounds(geometry)
.filterDate('2018-10-24','2019-06-30')
.map(M_ndvi);
// Run addTime on MODIS ImageCollection
var MODIS = ee.ImageCollection(MOD)
.filter(ee.Filter.date(START, END))
.map(addTime)
.filter(ee.Filter.inList('Date',ee.List(DATES)));
print('MODIS',MODIS);
// Combine MODIS and S2 Image Collections using Date
// Specify the join type
var join_type = ee.Join.inner();
// Set the join parameter
var filter = ee.Filter.equals({
leftField: 'Date',
rightField: 'Date'
});
// Execute the join
var inner_join = ee.ImageCollection(join_type.apply(MODIS,S2_resampled,filter));
// Flatten joined images into a single image with 2 bands
var S2_and_MOD = inner_join.map(function(feature) {
return ee.Image.cat(feature.get('primary'), feature.get('secondary'));
});
print('Combined S2 and MODIS Collection:',S2_and_MOD);
// Calculate the difference between S2 and MODIS NDVI values
var Diff = S2_and_MOD.map(function(img){
var clip = img.clip(geometry);
var Diffe = clip.expression('NDVI_S2 - NDVI_MOD',
{'NDVI_S2':clip.select('NDVI_S2') , 'NDVI_MOD':clip.select('NDVI_MOD')}).rename('Diff');
return Diffe
.copyProperties(img,['system:time_start','system:time_end']); });
print('NDVI Difference Collection',Diff);

How to get the difference image of this month and the previous month in Google Earth Engine with a smart way?

How to get the difference image of this month and the previous month in Google Earth Engine with a smart way?
study area 25E-75E,5S-35N。
// study area 25E-75E,5S-35N。
var geometry =
ee.Geometry.Polygon(
[[[25, 35],
[25, 5],
[75, 5],
[75, 35]]], null, false);
var regions = ee.FeatureCollection([
ee.Feature(geometry)
]);
// imgCol
var now = ee.Date(Date.now());
var NDVICollection=ee.ImageCollection('MODIS/006/MOD13Q1')
.filterDate('2010-01-01',now)
.filterBounds(regions)
.select('NDVI');
var col = NDVICollection.map(function(img){
return img.multiply(0.0001)
.copyProperties(img,['system:time_start','system:time_end']);
});
// grouped by month
var months = ee.List([11,12,1,2]);
var byMonth = ee.ImageCollection.fromImages(
months.map(function (m) {
return col.filterDate('2019-11-01',now).filter(ee.Filter.calendarRange(m, m, 'month'))
.select('NDVI').mean()
.set('month', m);
}));
mask
var meanNDVI = byMonth.reduce(ee.Reducer.mean());
var mask = meanNDVI.gt(0.1);
Create difference image
**var img12 = byMonth.filter(ee.Filter.eq('month', ee.Number(12))).first().updateMask(mask);
var img11 = byMonth.filter(ee.Filter.eq('month', ee.Number(11))).first().updateMask(mask);
var img1 = byMonth.filter(ee.Filter.eq('month', ee.Number(1))).first().updateMask(mask);
var img2 = byMonth.filter(ee.Filter.eq('month', ee.Number(2))).first().updateMask(mask);
var ndviChange_12 = img12.subtract(img11).set('name','ndviChange_12');
var ndviChange_1 = img1.subtract(img12).set('name','ndviChange_1');
var ndviChange_2 = img12.subtract(img1).set('name','ndviChange_2');
var ndviChange = ee.ImageCollection([ndviChange_12,ndviChange_1,ndviChange_2]);**
I want make it much more smart, what should I do? make a function or something else?
Show the image
Map.centerObject(regions);
Map.addLayer(byMonth);
Map.addLayer(ndviChange);
I think the solution is to use iterate on your byMonth collection . Check this example in the documentations.
https://developers.google.com/earth-engine/ic_iterating

Resources