本文将介绍在GEE中,如何理解和使用遥感数据的质量控制QA波段,以及介绍使用QA波段制作掩膜和去云的过程。
一、2024年10月31日答疑:
1.有粉丝问:L8是怎么用QA_PIXEL来掩膜掉云和噪声的吗,问了AI,还是没懂这些参数什么意思,为什么移位1<<5就是第六位,也不知道每一行什么意思。代码如下:
var cloudMaskL8=function(image){
var qa=image.select('QA_PIXEL');
var cloud=qa.bitwiseAnd(1<<2)
.or(qa.bitwiseAnd(1<<5))
.or(qa.bitwiseAnd(1<<7))
.or(qa.bitwiseAnd(1<<4))
.or(qa.bitwiseAnd(1<<3))
.or(qa.bitwiseAnd(1<<8).and(qa.bitwiseAnd(1<<9)))
.or(qa.bitwiseAnd(1<<10).and(qa.bitwiseAnd(1<<11)))
.or(qa.bitwiseAnd(1<<12).and(qa.bitwiseAnd(1<<13)))
.or(qa.bitwiseAnd(1<<14).and(qa.bitwiseAnd(1<<15)));
return image.select([
'SR_B2','SR_B3','SR_B4','SR_B5','SR_B6','SR_B7'],
['blue','green','red','nir','swir1','swir2']).updateMask(cloud.not());
};
var cloudMaskL457=function(image){
var qa=image.select('QA_PIXEL');
var cloud=qa.bitwiseAnd(1<<5)
.or(qa.bitwiseAnd(1<<7))
.or(qa.bitwiseAnd(1<<3))
.or(qa.bitwiseAnd(1<<4))
.or(qa.bitwiseAnd(1<<8).and(qa.bitwiseAnd(1<<9)))
.or(qa.bitwiseAnd(1<<10).and(qa.bitwiseAnd(1<<11)))
.or(qa.bitwiseAnd(1<<12).and(qa.bitwiseAnd(1<<13)))
.or(qa.bitwiseAnd(1<<14).and(qa.bitwiseAnd(1<<15)));
return image.select([
'SR_B1','SR_B2','SR_B3','SR_B4','SR_B5','SR_B7'],
['blue','green','red','nir','swir1','swir2']).updateMask(cloud.not());
};
答:简单来说,就是数据是以二进制01这种格式保存的,以哨兵数据的QA60波段为例,假如有一个像素是111001111000,(bit10就是从右往左数第10个数字,从0开始数到10。10位相当于从1数第11个数字)。10位是1就是有云,0就是无云。例子的第10位数字是1,所以现在该像素是有云的。1<<10就是把0001左移10位,变成10000000000。现在将像素值111001111000和10000000000作比较,两个数字重叠一下,如果111001111000的第10位是1,那么就是有云,这个过程就是qa.bitwiseAnd(cloudBitMask)。And是布尔运算,如果第10位数字匹配返回1,不匹配返回0。就是说如果两数的布尔运算结果是1就是有云,0就是无云。.updateMask()是将无云的像素保留。
为什么这么做呢?是因为数据中的二进制数字中包含了很多信息,不光是云,卷云,可能还有其他信息(雪、阴影、水体、冰等)。比如该代码中有5,6,7,8,9,10,11,12,13,14,15。单独比较其中1位,不会造成误判,简化了判断流程。
二、粗浅理解
比如Sentinel-2数据的 ‘QA60’ 波段,包含Opaque clouds不透明的云和Cirrus clouds卷云
① qa.bitwiseAnd(cloudBitMask).eq(0) 表示选择cloudBitMask
比特位为10的数据左移一位,并且让bit10位置的值等于0,这样就生成了云掩膜。
② qa.bitwiseAnd(cirrusBitMask).eq(0) 表示选择 cirrusBitMask 比特位为11的数据左移一位,并且让bit11位置等于0,这样生成了卷云的掩膜。
③ 使用 and() 将两个掩膜合并加起来生成云和卷云的共同的大掩膜mask。
④ 使用 .updateMask(mask) 更新掩膜,将无云的影像筛选出来。
符号 | 描述 | 运算规则 |
---|---|---|
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
这里的1<<10或者1<<11要换算成二进制位运算,左移10位或者11位,右边用0补位 |
经过CFMASK算法处理后生成一个QA60,QA60在bit10和bit11是Cloud mask(二进制表示,存在Cloud mask即为1,不存在为0)
三、去云以前效果
四、去云以后效果
代码
//导入数据
var s2 = ee.ImageCollection("COPERNICUS/S2"),
point = ee.Geometry.Point([112.20553071765003, 26.404020061278715]);
S2去云
//s2去云
function maskS2clouds(image) {
var qa = image.select('QA60');
// Bits 10 and 11 are clouds and cirrus, respectively.
//比特10和比特11分别是云和卷云。
var cloudBitMask = 1 << 10;
var cirrusBitMask = 1 << 11;
// Both flags should be set to zero, indicating clear conditions.
//两个标志都应该设置为零,以指示清除条件
var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
.and(qa.bitwiseAnd(cirrusBitMask).eq(0));
return image.updateMask(mask).divide(10000);
}
var startDate = "2020-6-4";
var endDate = "2020-6-30";
Map.centerObject(point, 8);
var s2Imgs = s2.filterDate(startDate, endDate)
.filterBounds(point);
Map.addLayer(s2Imgs.first(), {min:0, max:3000, bands:["B4", "B3", "B2"]}, "raw", false);
//影像集每幅影像去云
s2Imgs = s2Imgs.map(maskS2clouds);
//选择影像集第一幅影像去云,合成,显示
Map.addLayer(s2Imgs.first(), {min:0, max:3000, bands:["B4", "B3", "B2"]}, "cloud");