GEE中在自定义水体掩膜上计算NDCI指数报错如何解决
问题背景
基于GEE平台处理Sentinel-2 SR影像,开展区域水体叶绿素a浓度反演工作,预设掩膜规则为:水体像元值为1,陆地像元值为0(透明),需要在已构建的水体掩膜范围内计算归一化叶绿素a指数(NDCI)。运行代码时触发如下报错:
ImageCollection (Error):ID为20200106T114451_20200106T114531_T29UNV的影像执行map映射时出错,错误提示为
Image.select: Pattern 'mask' did not match any bands
原问题附实现代码如下:
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)
报错根因
- API用法错误:GEE中
Image.mask()不存在传入影像自动生成名为mask波段的逻辑,无参调用时返回影像当前掩膜,传入参数时是为影像设置新掩膜、返回原影像调整掩膜后的结果,因此代码中addBands(mask)添加的并非名为mask的波段,后续执行.select('mask')自然匹配不到对应波段触发报错。 - 流程逻辑断层:代码拆分了NDWI水体掩膜计算、NDCI计算两个独立步骤,还单独取了第一景NDWI影像
bb做掩膜源,既无法保证每景时序影像和水体掩膜空间匹配,也没有实现“掩膜范围内计算NDCI”的核心需求。 - 波段筛选时机错误:在完成指数计算前提前筛选单波段(如
.select('NDWI')、.select('NDCI')),导致后续步骤丢失原始反射率波段,无法支撑跨步骤的指数计算。
修正方案
- 废弃错误的
MASK映射函数,将云掩膜、NDWI水体提取、水体掩膜应用、NDCI计算整合到单景影像的处理函数中,每景影像独立完成全流程计算,避免时序影像掩膜错位。 - 调整波段筛选时机,所有指数计算完成后再按需选择输出波段,保证计算过程中B3、B4、B5、B8等原始反射率波段可正常调用。
- 直接通过
updateMask()实现掩膜挂载,不需要额外生成独立掩膜波段再做筛选匹配。
修正后可运行代码
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 calWaterAndNDCI = function(image){ // 计算NDWI提取水体范围 var NDWI = image.normalizedDifference(['B3', 'B8']).rename('NDWI'); // 应用水体掩膜,仅保留水体像元 var waterOnlyImg = image.updateMask(NDWI.gt(0)); // 在水体范围内计算NDCI var NDCI = waterOnlyImg.normalizedDifference(['B5', 'B4']).rename('NDCI'); // 返回挂载NDWI、NDCI波段的结果,保留原始反射率波段备用 return waterOnlyImg.addBands([NDWI, NDCI]) .copyProperties(image, ["system:time_start"]); }; // 生成最终成果影像集合 var resultCollection = minmin.map(calWaterAndNDCI); print("水体范围NDCI成果集合", resultCollection); // 加载第一景结果做可视化验证 var checkImg = resultCollection.first(); Map.addLayer(checkImg.select('NDWI'), {min:0, max:1, palette:['ffffff','1565c0']}, '水体掩膜'); Map.addLayer(checkImg.select('NDCI'), {min:-0.2, max:0.4, palette:['2196f3','4caf50','ffeb3b','f44336']}, '叶绿素a指数NDCI');
内容的提问来源于stack exchange,提问作者Minyan Zhao
相关产品推荐
相关产品推荐

