摘要:本文介绍了如何加载Landsat8影像,包括如何应用缩放因子,如何去云,并提供了可以直接运行的示例代码。
相信大部分初学者在GEE运行的第一个代码就是加载影像的代码,在点下run的一瞬间,以前可望不可及的大量影像铺满了在祖国大地,然而看似简单的加载影像,如果这几个地方处理的不够得当,将为后续的研究埋下深深的雷。
- 应用缩放因子
众所周知,原始影像反射率的值是0-1之间浮点数,出于节省存储空间的考虑,GEE平台会将影像转换为16位的整型,因此我们在使用影像时要应用缩放因子还原影像的真实反射率。有的同学参考的教程里没有应用缩放因子,在计算NDVI等归一化指数时并不会受影响,但是在计算以加减法运算为主指数时就会造成数量级上的错误,从而在后续的研究中始终跑不出正确的结果。不同的影像应用不同的缩放因子,这里以Landsat8的官方示例来做演示。
- 如何正确的去云
2.1 使用CLOUD_COVER属性去云(不推荐)
去云本身很简单的一个事,好多教程(主要集中在CSDN)写的真是一言难尽。初学者基本都是面像百度编程,搜出来的教程真是一学一个不吱声。
比如下面这个代码使用filter(ee.Filter.lt('CLOUD_COVER',2))来去云。
每一景影像都有一个叫CLOUD_COVER的属性,表示这一景影像被云覆盖面积的百分比。
filter(ee.Filter.lt('CLOUD_COVER',2))表示只保留云覆盖面积小于2%的影像。也就是说只要某一景影像的云面积大于2%就直接丢弃不用了,这也太浪费了吧,这样操作很容易导致加载出来的影像数量过少,甚至连研究区都盖不住。要是想针对特定的某几景影像做研究,这种方法也无可厚非,但是大多数情况下都是要将多景影像中位数合成的,这么做完全就是画蛇添足。因此,我们真正需要的去云是通过去云函数来对有云的像素进行去除。
2.2 使用去云函数去云(推荐)
实名反对某CSND教程:
代码是没有任何感情的,是绝对客观的存在,对就是对,错就是错,写出的代码实现不出相应的效果,不去排查自己代码中的bug,反而将对错归因于运气,我不理解。诚然写教程不用像写论文需要严谨,但是也不能搞得这么玄乎吧。
尽管Landsat8的官方示例未包含去云处理,但是从波段介绍中可以看出GEE是考虑到去云的需求的。以Landsat8为例,QA_PIXEL波段会将被云覆盖的像素标记出,因此只要使用updateMask函数将有云的像素去除就能达到去云的目的。
完整代码如下(可直接运行):
var roi = ee.Geometry.Polygon(
[[[98.76874122458284, 27.476046782884104],
[98.76874122458284, 26.36424630156598],
[100.16400489645784, 26.36424630156598],
[100.16400489645784, 27.476046782884104]]], null, false);
var maskclouds = function (img) {
var cloudShadowBitMask = 1 << 4;
var cloudsBitMask = 1 << 3;
var qa = img.select("QA_PIXEL");
var mask = qa
.bitwiseAnd(cloudShadowBitMask)
.eq(0)
.and(qa.bitwiseAnd(cloudsBitMask).eq(0));
return img.addBands(img.updateMask(mask), null, true);
};
var applyScaleFactors = function (image) {
var opticalBands = image
.select(["Blue", "Green", "Red", "NIR", "SWIR1", "SWIR2"])
.multiply(0.0000275)
.add(-0.2).float();
return image.addBands(opticalBands, null, true);
};
var imageCol = ee.ImageCollection("LANDSAT/LC08/C02/T1_L2")
.select(
["SR_B2", "SR_B3", "SR_B4", "SR_B5", "SR_B6", "SR_B7", "QA_PIXEL"],
["Blue", "Green", "Red", "NIR", "SWIR1", "SWIR2", "QA_PIXEL"]
)
.filterBounds(roi)
.filter(ee.Filter.lt('CLOUD_COVER',2))
.filterDate('2021-01-01', '2021-12-31')
.map(maskclouds)
.map(applyScaleFactors);
var image_median = imageCol.median().clip(roi);
var visualization = {
bands: ['Red', 'Green', 'Blue'],
min: 0.0,
max: 0.3,
};
Map.centerObject(roi, 8);
Map.addLayer(image_median, visualization, 'image_median');