简介本资源是一份面向地理信息、遥感与环境科学领域初学者与科研人员的《GEE中文学习教程》PDF文档系统填补国内Google Earth Engine平台基础教学资料的空白。教程由王金柱编写从地理学思维切入涵盖GEE核心概念空间发现、叠加分析、数据类型栅格与矢量、坐标系统、图形界面数据浏览器/代码编辑器/地图视图及GUI下的地形分析与遥感分类等实操模块并延伸至API脚本编写与大尺度时间序列分析方法助力用户高效处理Landsat、Sentinel等卫星数据。资源为单文件PDF格式共1个文件大小9.21MB内容结构清晰、案例导向明确含完整目录与代码实践注释。目前已有15799人学习下载适合零基础入门者建立GEE认知框架也便于进阶用户快速查阅GUI操作逻辑与遥感分析流程。1. GEE中文学习教程.pdf不是编程课是地理科研人员的“遥感计算器”速成手册你有没有试过——在ArcGIS里裁剪一个省级DEM等37分钟导出坡度图再等22分钟最后叠加透明度调到70%看效果发现边界对不上又得重来我去年帮某高校做长江中游湿地变化分析时就卡在这一步。直到把同样流程搬进GEE4行代码、11秒出图、结果直接可导出GeoTIFF。这不是玄学是王金柱老师这本《GEE中文学习教程.pdf》里第1节就点破的本质GEE不是让你写Python爬虫的平台而是把遥感数据当“算盘珠子”拨着用的地理科研计算器。它不考你for循环写得漂不漂亮只问你“想看哪片地、哪段时间、哪类变化”。教程从故宫定位开始教Map.setCenter()用重庆DEM山体阴影对比ArcGIS操作步骤逐行注释连没碰过JavaScript的某导师都能照着敲出第一张渲染图。全书覆盖Landsat/Sentinel/MODIS三大主力数据源的调用逻辑、FeatureCollection裁剪技巧、Reducer聚合陷阱甚至把Date Range怎么避开云层遮挡这种血泪经验都塞进第9节。它解决的不是“怎么学编程”而是“怎么让遥感分析从‘等结果’变成‘调参数’”——这才是国内地理、生态、农林领域研究者真正缺的那块拼图。2. 把GEE当地理工具用从空间发现到空间叠加的思维切换2.1 空间发现用坐标代替“双击缩放”建立地球尺度的空间直觉GEE的空间发现不是靠鼠标滚轮而是用地理坐标锚定观察焦点。教程第1.1.1节用故宫举例表面是教Map.setCenter(116.39, 39.91)实际在训练一种反直觉习惯所有空间操作必须先定义“我在哪、看多大”。这和Google Earth的搜索框逻辑完全不同——后者是“找东西”GEE是“设坐标系”。比如你要分析云南哀牢山保护区不能输“哀牢山”而要查该区域中心经纬度如101.5°E, 23.8°N再执行// 设置地图中心与缩放级别数字越小视野越大 Map.setCenter(101.5, 23.8, 8); // 8级缩放约等于1:10万比例尺 // 加载底图注意GEE默认底图是地形图非卫星图 Map.setOptions({basemap: SATELLITE}); // 强制切到卫星影像底图提示Map.setCenter()的第三个参数是缩放级别不是分辨率GEE的缩放级别遵循Google Maps标准0级为全球22级为单栋建筑。常用科研尺度省级用4-5级地市级用6-7级县域用8-9级。别盲目调高否则会触发“Too many pixels”报错。为什么必须这样因为GEE所有后续操作如clip()裁剪、reduceRegion()统计都依赖这个坐标系。如果跳过这步直接加载数据系统会默认用你账号注册地坐标导致云南的数据被画在黑龙江上——这是新手翻车率最高的坑之一。2.2 空间叠加用代码复刻ArcGIS工作流但绕开图层管理黑洞教程第1.1.2节的重庆DEM案例本质是教你怎么把ArcGIS里“拖拽-右键-属性-筛选-裁剪-工具箱-设置透明度”这一套动作翻译成7行可复用的代码。关键不在语法而在理解GEE的叠加逻辑是“数据流驱动”而非“图层堆叠”。ArcGIS里你可能同时开着10个图层靠眼睛判断谁在上谁在下GEE里所有叠加必须显式声明顺序// 步骤1加载原始DEM全球SRTM数据 var DEM ee.Image(USGS/SRTMGL1_003); // 步骤2加载中国省界矢量注意这是FeatureCollection不是单个面 var China_Provinces ee.FeatureCollection(users/wangjinzhulala/China_Provinces); // 步骤3筛选重庆filterMetadata返回新集合first()取第一个要素 var Chongqing China_Provinces.filterMetadata(NAME,equals,Chong_Qing).first(); // 步骤4用重庆几何体裁剪DEMclip()要求输入Geometry所以加.geometry() var DEM_Chongqing DEM.clip(Chongqing.geometry()); // 步骤5生成山体阴影Terrain.hillshade返回Image var HillShade_Chongqing ee.Terrain.hillshade(DEM_Chongqing); // 步骤6添加原始DEM到地图指定可视化参数 Map.addLayer(DEM_Chongqing, { bands: [elevation], min: 0, max: 2500, palette: [ff6a13,e8ff2d,60ff56] // 橙-黄-绿渐变对应低-中-高地势 }, DEM_ChongQing); // 步骤7叠加山体阴影opacity控制透明度值0-1 Map.addLayer(HillShade_Chongqing, { opacity: 0.7, bands: [hillshade] }, HillShade_ChongQing);这段代码的威力在于每一步输出都是确定性对象。DEM_Chongqing是裁剪后的栅格图像Chongqing是矢量面HillShade_Chongqing是派生图像。它们不像ArcGIS图层那样会因刷新丢失而是永久存在于GEE的计算图中。这也是为什么教程强调“不要把GEE当软件要当计算器”——你按下的每个键.clip()、.hillshade()都在构建一个可追溯、可修改、可嵌套的数学表达式。2.3 避坑空间操作三大幻觉与真实解法GEE的空间操作最容易陷入“我以为”的幻觉。以下是某跨平台系统开发中踩过的坑教程虽未明说但代码示例已埋下伏笔现象1Map.centerObject()后地图一片空白或显示位置完全错误→ 原因centerObject()要求输入Geometry对象但新手常传入Feature或FeatureCollection。例如Map.centerObject(China_Provinces)会失败因为China_Provinces是集合不是单个几何体。→ 解决强制提取几何体——Map.centerObject(China_Provinces.geometry())或用first().geometry()取首个要素几何。现象2裁剪后图像边缘出现黑色锯齿或部分区域缺失→ 原因clip()操作默认使用输入Feature的外包矩形bounding box裁剪而非精确几何边界。当重庆边界是复杂多边形时外包矩形会包含大量四川、贵州区域导致裁剪结果包含无效像素。→ 解决改用clipToCollection()并指定bestEffort: true参数var DEM_Clipped DEM.clipToCollection(Chongqing).set(crs, EPSG:4326);此方法强制按矢量边界精确裁剪且set(crs)确保坐标系统一避免投影变形。现象3叠加山体阴影后颜色发灰、对比度极低看不出地形起伏→ 原因ee.Terrain.hillshade()输出值域为0-255但默认可视化参数min:0, max:255未适配实际地形范围。重庆海拔0-3000米但山体阴影值集中在50-180区间拉满0-255就洗白了。→ 解决动态计算值域并重设可视化var stats HillShade_Chongqing.reduceRegion({ reducer: ee.Reducer.minMax(), geometry: Chongqing.geometry(), scale: 30, maxPixels: 1e13 }); Map.addLayer(HillShade_Chongqing, { min: ee.Number(stats.get(hillshade_min)).getInfo(), // 实际最小值 max: ee.Number(stats.get(hillshade_max)).getInfo(), // 实际最大值 palette: [black, white] }, HillShade_Adaptive);此方案用reduceRegion()实测当前区域的明暗值比硬编码min:0,max:255可靠十倍。3. GUI与Code Editor双模操作图形界面不是玩具是调试黑匣子的探针3.1 GUI构成解析数据浏览器、代码编辑器、地图视图的三角验证关系教程第2节看似讲GUI界面实则在建立一套三维验证体系数据浏览器确认“数据存在”代码编辑器确认“逻辑正确”地图视图确认“结果可视”。三者缺一不可尤其对遥感新手——你永远不知道是代码写错了还是数据本身有云或是可视化参数坑了你。数据浏览器左侧面板不是文件夹是“数据API索引”。输入Landsat能搜出27个数据集但教程第8.1节明确指出LANDSAT/LC08/C02/T1_L2Landsat 8 Collection 2 Level 2才是2013年后首选因已做大气校正SR产品而LANDSAT/LC08/C01/T1_TOA需自行处理辐射定标。代码编辑器中央面板教程第3节强调其分栏设计——左侧“Scripts”存你写的脚本右侧“Imports”管外部库下方“Console”实时打印print()结果。关键技巧按CtrlEnter运行当前脚本但务必先点选脚本名再运行否则可能执行上一个未保存的草稿。地图视图右侧面板教程第2.1.1节提到“点击卫星按钮”但没说的是地图右上角的“Layers”图标才是真相开关。点开后能看到所有addLayer()添加的图层勾选/取消即显隐拖动图层顺序即改变叠加层级——这比代码里写Map.addLayer()更直观调试。注意GUI所有操作都会实时转译为JavaScript代码。当你在数据浏览器里点选“Sentinel-2 MSI”并拖到地图编辑器会自动生成var image ee.Image(COPERNICUS/S2_SR/20230515T030549_20230515T030544_T49QGD);。这是教程没写的隐藏功能把GUI当代码生成器用。3.2 GUI运算与分析用点选替代手写Reducer但必须懂底层逻辑教程第2.2节演示GUI做NDVI计算表面是点几下按钮实际在教你怎么绕过normalizedDifference()函数的手动编写。但新手常犯的错是点了“NDVI”按钮结果图一片红——因为没设波段名。Sentinel-2的红波段是B04近红外是B08而Landsat 8是B5和B4。GUI不会自动识别必须手动填Red band: B04 NIR band: B08更隐蔽的坑在时间范围选择。GUI默认选“最近7天”但Sentinel-2重访周期是5天云量常超80%。教程第8.1节表格里写着“Sentinel 2A MSI 时间分辨率10day”却没说10天是理论值实际可用影像可能间隔30天。某次我用GUI选2023年6月数据结果加载的是6月1日和6月30日两张云图NDVI计算全废。3.3 利用GUI做地形分析与遥感分类从“点一下”到“为什么这么点”教程第2.3节的地形分析案例核心是教会你读透GUI背后的数据流。比如“坡度分析”按钮点下去前必须确认输入数据是DEM如SRTM不是光学影像输出单位是“度”还是“百分比”GEE默认输出弧度GUI会自动转度分辨率匹配SRTM是30m若你加载10m Sentinel-2影像做坡度GUI会强制重采样导致精度损失。遥感图像分类同理。GUI的“监督分类”功能要求你先画训练样本ROI但教程第2.3.2节没展开的是ROI必须覆盖所有地物类型且每类样本数30个像素。某次我用GUI画了5个水稻田点分类结果全是噪声——因为GEE的随机森林分类器需要足够样本学习光谱特征。后来按教程第11.1节改用代码// 手动定义训练样本比GUI更可控 var training rice_roi.merge(forest_roi).merge(urban_roi); var classifier ee.Classifier.smileRandomForest(10).train({ features: training, classProperty: landcover, inputProperties: [B2,B3,B4,B8] // 显式指定Sentinel-2波段 }); var classified image.classify(classifier);代码虽多3行但inputProperties锁死波段classProperty绑定标签彻底规避GUI的模糊性。3.4 避坑GUI操作四大认知偏差与代码级修正GUI的便利性是把双刃剑以下偏差在某图像处理Demo中反复出现现象1在GUI里加载Landsat 5数据地图显示正常但导出时提示“Image is empty”→ 原因GUI自动加载的是LANDSAT/LT05/C01/T1_TOALevel 1 TOA但该数据集2011年后无新影像且部分轨道数据缺失。空图像不是代码错是数据源枯竭。→ 解决强制切换到Collection 2在数据浏览器搜LANDSAT/LT05/C02/T1_L2或代码中写死var l5 ee.ImageCollection(LANDSAT/LT05/C02/T1_L2) .filterDate(1985-01-01, 2012-05-01);现象2GUI做的NDVI图颜色鲜艳但导出的GeoTIFF打开是纯灰→ 原因GUI可视化用的是动态拉伸自动算min/max而导出时用原始DN值。NDVI理论值域-1~1但导出TIFF常存为Int16-1→-327681→32767普通看图软件无法识别。→ 解决导出前用visualize()固化色彩Export.image.toDrive({ image: ndvi.visualize({min: -1, max: 1, palette: [red,white,green]}), description: NDVI_Visualized, scale: 30, region: roi });现象3GUI里“重采样”选项调成“bilinear”但结果仍锯齿明显→ 原因“重采样”只影响地图显示不影响计算。clip()、reduceRegion()等运算仍用原始分辨率。锯齿是显示缩放导致非数据问题。→ 解决地图视图右下角点“Scale”查看当前分辨率若显示“30m”但图像模糊说明浏览器缩放过度按Ctrl0重置。现象4GUI分类结果图层关闭后再打开变成全黑→ 原因GUI分类结果是临时内存对象关闭图层即释放。不像代码中classified变量持久存在。→ 解决GUI做完分类立刻点“Save”按钮存为Asset教程第3.2节提过或用代码导出Export.table.toAsset({ collection: classified.reduceToVectors({ // 转矢量便于GIS分析 geometry: roi, scale: 30, labelProperty: class }), description: Classification_Asset });4. 从基础数据类型到空间对象String/Number到FeatureCollection的建模跃迁4.1 基础类型为什么String和Number的坑都在“隐式转换”里教程第4节讲String和Number看似简单实则埋着GEE最深的雷区——JavaScript弱类型在遥感场景下的灾难性表现。比如你写var year 2023; // String类型 var image ee.ImageCollection(LANDSAT/LC08/C02/T1_L2) .filterDate(year -01-01, year -12-31); // 字符串拼接OK这没问题。但若写var year 2023; // Number类型 var image ee.ImageCollection(LANDSAT/LC08/C02/T1_L2) .filterDate(year -01-01, year -12-31); // 错2023-01-01 2023-01-01 → NaNGEE会静默返回空集合地图啥也不显示。教程第4.1节用ee.String()强制转换但更安全的是var year 2023; var startDate ee.Date.fromYMD(year, 1, 1); // 用ee.Date构造类型安全 var endDate ee.Date.fromYMD(year, 12, 31);Number类型更危险。教程第4.2节说ee.Number(3.14)但没警告GEE所有数值计算默认用64位浮点但遥感DN值常是16位整型。某次我用image.multiply(0.0000275).add(-0.2)做Landsat 8辐射定标结果NDVI全乱——因为0.0000275在二进制浮点下是无限循环小数累积误差达0.0001对植被指数致命。解决方案是用ee.Image.constant()var mult ee.Image.constant(0.0000275); var add ee.Image.constant(-0.2); var calibrated image.multiply(mult).add(add);constant()创建的图像是精确值非浮点近似。4.2 复合类型Dictionary/List/Array如何成为遥感元数据的骨架教程第5节的Dictionary表面是键值对实则是遥感数据的元数据容器。比如Landsat 8影像的system:time_start字段存毫秒时间戳CLOUD_COVER存云量百分比。新手常直接print(image.get(CLOUD_COVER))但返回的是ComputedObject——因为GEE延迟计算。必须用getInfo()var cloudCover image.get(CLOUD_COVER).getInfo(); // 同步获取真实值 if (cloudCover 20) { // 过滤云量20%的影像 // 处理... }List是GEE的“数组”但教程第5.2节没强调List索引从0开始且不可变。你不能list[0] newValue只能用list.set(0, newValue)。某次我写var bands [B2,B3,B4]; bands[0] B1;结果bands还是原样——因为JavaScript数组和GEE List是两套体系。Array是数值计算专用教程第5.3节的ee.Array()用于矩阵运算。比如计算NDVI的向量化公式// 传统写法慢 var ndvi image.normalizedDifference([B8, B4]); // Array写法快适合批量处理 var nir image.select(B8).toArray(); var red image.select(B4).toArray(); var ndviArray nir.subtract(red).divide(nir.add(red));但Array不支持addLayer()必须转回ImagendviArray.arrayProject([0]).arrayFlatten([[ndvi]])。4.3 空间对象Geometry/Feature/FeatureCollection的三层抽象教程第6节是GEE的“宪法”定义了所有空间操作的根基。Geometry纯粹的几何体无属性。ee.Geometry.Polygon()画的多边形就是Geometry。坑在于Geometry必须指定坐标系。教程示例用ee.Geometry.Polygon(coords)但没写{crs: EPSG:4326}。若你用UTM坐标画Polygon不声明CRSGEE默认当WGS84位置偏移千米级。FeatureGeometry属性。教程第6.2节的ee.Feature(geometry, properties)关键在properties必须是Object不能是List。某次我传{area: [12345]}结果面积字段显示[12345]而非12345reduceRegion()统计全错。FeatureCollectionFeature的集合教程第6.3节强调它是“可查询、可过滤、可映射”的核心容器。但新手不知FeatureCollection的size()方法返回ee.Number不能直接print(collection.size())必须.getInfo()。提示FeatureCollection的filterBounds()比filterMetadata()快10倍。前者用空间索引后者遍历属性表。做区域筛选优先用filterBounds(roi)。4.4 避坑数据类型五大隐形陷阱与防御式写法某遥感项目X中这些坑导致3次数据交付延期现象1print(feature.get(NAME))输出null但ArcGIS里明明有NAME字段→ 原因GEE区分大小写且字段名可能含空格或特殊字符。中国省界数据中字段名实为name小写或NAME_1。→ 解决先用feature.propertyNames().getInfo()查真实字段名再取值。现象2List.get(0)报错“Index out of bounds”但List.length()显示5→ 原因List.length()返回ee.Number需.getInfo()转JS数字。List.get(0)时List可能为空如filter()无结果但.length()不报错。→ 解决防御式取值var list ee.List([1,2,3]); var first ee.Algorithms.If(list.length().gt(0), list.get(0), null);现象3FeatureCollection.toList(1000)后get(500)返回Feature但geometry()报错→ 原因toList()返回的List里元素是ee.ComputedObject不是原Feature。必须用get()后强转var fc ee.FeatureCollection(path); var list fc.toList(1000); var feature ee.Feature(list.get(500)); // 强制转Feature var geom feature.geometry();现象4Dictionary.keys()返回[a,b,c]但Dictionary.get(a)是null→ 原因Dictionary的key是字符串但keys()返回的是ee.Listget()需索引而非key。正确取法Dictionary.get(a)是对的但若key不存在返回null。→ 解决用contains()预检var dict ee.Dictionary({a: 1, b: 2}); var hasA dict.contains(a); // 返回ee.Boolean现象5Array.cat()合并两个Array结果维度错乱arrayLength()报错→ 原因cat()是横向拼接hstack若两Array行数不同结果为不规则矩阵。GEE Array要求严格矩形。→ 解决用concat()替代或先reshape()统一分辨率var arr1 ee.Array([[1,2],[3,4]]); var arr2 ee.Array([[5,6]]); // 1x2 var arr2_fixed arr2.reshape([1,2]); // 强制1x2 var merged arr1.cat(arr2_fixed, 1); // 沿列拼接5. Image与ImageCollection遥感大数据的加载、筛选与合成策略5.1 Image单景影像的加载与预处理链教程第7.1节说ee.Image()加载单景但没写全加载路径的三种模式ID加载ee.Image(LANDSAT/LC08/C02/T1_L2/LC08_123045_20230515)精准但需知道IDCollection筛选ee.ImageCollection(...).filterMetadata(WRS_PATH,equals,123).first()灵活但慢Asset加载ee.Image(users/username/my_preprocessed_image)最快适合存中间结果。预处理链是GEE的灵魂。教程第7.1节示例只做辐射定标但实战必须加var image ee.Image(LANDSAT/LC08/C02/T1_L2/LC08_123045_20230515) .multiply(ee.Image.constant([0.0000275, 0.0000275, 0.0000275])) // B4,B3,B2 .add(ee.Image.constant([-0.2, -0.2, -0.2])) .clamp(0, 1) // 限定0-1防负值 .updateMask(ee.Image(LANDSAT/LC08/C02/T1_L2/LC08_123045_20230515).select(QA_PIXEL).bitwiseAnd(13).eq(0)); // 掩膜云clamp()防辐射定标溢出updateMask()用QA波段去云——教程第8.1节提了QA_PIXEL但没给位运算示例。5.2 ImageCollection时间序列的构建与降噪艺术教程第7.2节强调filterDate()和filterBounds()但时间序列分析真正的难点在降噪。Landsat 16天一景但云、雪、阴影让有效数据稀疏。教程第10.1节Filter只讲基础实战需组合var collection ee.ImageCollection(LANDSAT/LC08/C02/T1_L2) .filterBounds(roi) .filterDate(2020-01-01, 2023-12-31) .filterMetadata(CLOUD_COVER, less_than, 20) // 云量20% .map(function(image) { var cloudShadow image.select(QA_PIXEL).bitwiseAnd(14).neq(0); // 阴影位 var cloud image.select(QA_PIXEL).bitwiseAnd(13).neq(0); // 云位 var mask cloudShadow.or(cloud).not(); // 取反得有效像元 return image.updateMask(mask).copyProperties(image, [system:time_start]); });copyProperties()保留时间戳否则reduce()后时间信息丢失。5.3 Landsat Images深度解析Collection 1 vs Collection 2的生死抉择教程第8.1节表格列了Landsat数据但没说清Collection 2C02为何是唯一选择C01已停更2022年起Landsat 8/9只发C02数据C02有SR产品地表反射率已做大气校正免去FLAASH等复杂流程C02 QA_PIXEL更准用QA_PIXEL波段比PIXEL_QA云检测精度高15%。某次我用C01做长江口悬浮物反演结果与实测偏差30%换C02后降至5%——因为C01的辐射定标系数有系统误差。5.4 Confusion Matrix分类精度验证的GEE原生实现教程第8.2节讲混淆矩阵但只给errorMatrix()函数。实战需闭环验证// 1. 生成分类结果 var classified image.classify(classifier); // 2. 采样验证点用stratifiedSample保证各类均衡 var validation classified.stratifiedSample({ numPoints: 500, classBand: classification, region: roi, scale: 30 }); // 3. 构建混淆矩阵 var matrix ee.ConfusionMatrix(validation, classification, sample); // 4. 计算Kappa系数教程没给但必用 var kappa matrix.kappa().getInfo(); print(Kappa:, kappa); // 0.8为优stratifiedSample()比randomPoints()可靠避免某类样本为0。5.5 避坑ImageCollection四大时效性陷阱与应对某湿地监测项目中这些坑让季度报告延误现象1collection.size().getInfo()返回0但数据浏览器里明明有影像→ 原因size()是服务器端计算若filterBounds()的roi超出影像覆盖范围如用全球roi查单景返回0。→ 解决先collection.toList(1).size()测试或用collection.first().geometry().intersects(roi)预检。现象2collection.sort(CLOUD_COVER)后first()仍是云图→ 原因sort()按字段值升序CLOUD_COVER越小越好但某些影像该字段为nullnull排在最前。→ 解决过滤掉nullvar filtered collection.filter(ee.Filter.notNull([CLOUD_COVER])); var sorted filtered.sort(CLOUD_COVER);现象3collection.mosaic()合成后时间戳变成1970年→ 原因mosaic()取最新像素但不继承时间属性。system:time_start丢失。→ 解决手动赋值var mosaic collection.mosaic() .set(system:time_start, ee.Date(2023-01-01).millis());现象4collection.map()里用image.date()结果全是同一时间→ 原因image.date()返回ee.Date对象需.millis()转毫秒才能参与计算。直接print(image.date())显示Date非真实值。→ 解决var withTime collection.map(function(image) { var time ee.Number(image.date().millis()); return image.set(timestamp, time); });6. 参数类型实战Date/Filter/Reducer的组合技与反直觉配置6.1 Date与Date Range时间维度的精确手术刀教程第9节讲ee.Date()但时间操作真正的难点在时区与精度。GEE所有时间戳用UTC但中国用户常误用北京时间UTC8。某次我设filterDate(2023-06-01, 2023-06-30)结果漏掉6月1日0-8点的影像——因为那些影像是UTC时间5月31日16-24点。正确做法是用ee.Date.fromYMD()并指定时区var start ee.Date.fromYMD(2023, 6, 1).advance(-8, hour); // UTC时间北京时间-8h var end ee.Date.fromYMD(2023, 6, 30).advance(16, hour); // 覆盖6月30日24点 var collection ee.ImageCollection(...).filterDate(start, end);DateRange用于filterDate()但教程第9.2节没提DateRange可嵌套。比如分析雨季5-9月多年变化var monsoonRanges ee.List.sequence(2020, 2023).map(function(y) { var year ee.Number(y); return ee.DateRange( ee.Date.fromYMD(year, 5, 1), ee.Date.fromYMD(year, 9, 30) ); }); var monsoonCollection ee.ImageCollection(...) .filter(ee.Filter.dateRangeContains(system:time_start, monsoonRanges));6.2 Filter从metadata到spatial的七种武器教程第10.1节只列filterMetadata()但实战需七种Filter组合filterBounds(roi)空间快速筛选filterDate(start, end)时间窗口filterMetadata(本文还有配套的精品资源点击获取