基于 GEE 利用 GHSL(100m)数据的区域建成区时空变化量化分析
目录
一、代码整体框架与设计思路
二、逐模块深度解析(含代码片段与逻辑拆解)
(一)模块 0:用户设置 —— 分析基础参数定义
(二)模块 1:数据集加载 ——GHSL 100m 数据筛选与校验
(三)模块 2:地图可视化 —— 年度建成区空间分布展示
(四)模块 3:年度建成区面积计算 —— 双场景验证确保精度
(五)模块 4:柱状图绘制 —— 年度面积变化趋势可视化
(六)模块 5:CSV 表格导出 —— 结果离线存储与二次分析
(七)模块 6:GeoTIFF 影像批量导出 —— 空间数据离线使用
(八)模块 7:数据单位诊断 —— 验证双场景合理性
三、代码运行流程与常见问题解决方案
四、总结
五、运行结果

若觉得代码对您的研究 / 项目有帮助,欢迎点击打赏支持!需要完整代码的朋友,打赏后可在后台私信(复制文章标题发给我),我会尽快发您完整可运行代码,感谢支持!
本代码基于 Google Earth Engine(GEE)平台,针对 JRC 发布的 GHSL 100 米分辨率建成区数据集(GHS_BUILT_S),实现从数据加载、可视化、面积计算到结果导出的全流程分析,核心目标是量化研究区域(ROI)内建成区的年度变化特征。以下从代码结构、关键逻辑、参数含义等维度进行逐模块深度解析。
一、代码整体框架与设计思路
代码采用 “参数配置→数据加载→可视化→计算→输出” 的线性流程,同时融入 “双场景验证”(建成区面积计算)和 “数据诊断”(单位判断)模块,确保结果可靠性。整体遵循 GEE 开发最佳实践:
- 优先使用服务器端运算(如
map、reduceRegion),避免大量getInfo()导致客户端卡顿; - 关键步骤添加
print语句,便于在 GEE 控制台校验数据完整性; - 批量导出与手动触发结合,平衡自动化效率与资源控制(避免 Drive 空间过载)。
二、逐模块深度解析(含代码片段与逻辑拆解)
(一)模块 0:用户设置 —— 分析基础参数定义
核心作用:指定分析范围、地图视角、导出路径,是后续所有步骤的 “全局变量”,需用户根据实际需求修改,直接影响分析结果的准确性。
// ------------- 0. 用户设置 -------------
var roi = table; // 研究区域(ROI)矢量边界
Map.centerObject(roi, 11); // 地图定位与缩放
var driveFolder = 'earthengine'; // Drive 导出文件夹名
| 参数名 | 含义与要求 | 潜在问题与解决方案 |
|---|---|---|
roi = table | 研究区域矢量数据,需提前在 GEE 中导入(格式支持 Shapefile、KML、GeoJSON 等),并命名为 “table” | 若未导入或命名错误,后续所有裁剪(clip)、面积计算(reduceRegion)会报错;解决方案:在 GEE 资产面板确认矢量数据名称,或修改代码中 table 为实际资产名(如 var roi = ee.FeatureCollection("users/xxx/your_roi")) |
Map.centerObject(roi, 11) | roi 为定位中心,11 为缩放级别(GEE 缩放级 0-24,数值越大视角越近,11 对应约 10 公里视野) | 缩放级别过大可能导致地图加载缓慢;解决方案:大范围 ROI 设为 8-10,小范围(如城市)设为 12-14 |
driveFolder = 'earthengine' | Google Drive 中存储导出文件的文件夹名称,需提前在 Drive 中创建(若不存在,导出时会自动创建) | 文件夹名含特殊字符(如空格、中文)可能导致导出失败;解决方案:使用英文、数字、下划线组合(如 GHSL_Export_2024) |
(二)模块 1:数据集加载 ——GHSL 100m 数据筛选与校验
核心作用:加载目标数据集,筛选关键波段,通过控制台输出校验数据完整性(如年份范围、投影信息),避免后续分析使用错误数据。
// ------------- 1. 加载 GHSL 100m 数据集 -------------
var ghsl100 = ee.ImageCollection('JRC/GHSL/P2023A/GHS_BUILT_S').select(['built_surface']) // 筛选建成区核心波段.filterBounds(roi); // 按 ROI 裁剪数据集// 数据校验:控制台输出关键信息
print('GHSL 100m 数据集影像数量:', ghsl100.size());
print('GHSL 100m 可用年份列表:', ghsl100.aggregate_array('system:index'));
print('首张影像元数据:', ghsl100.first());
-
数据集选择:
JRC/GHSL/P2023A/GHS_BUILT_S是 2023 版 GHSL 建成区数据集,分辨率 100 米,覆盖全球,年度更新(具体年份需通过system:index查看)。若需其他版本,可替换为JRC/GHSL/P2021A/GHS_BUILT_S(2021 版)等,需注意波段名称是否一致。 -
波段筛选:
select(['built_surface'])仅保留 “建成区表面” 波段,剔除数据集中可能包含的 “质量控制波段”(如built_surface_qc),减少数据量,提升运算效率。若误删关键波段,后续面积计算会因 “无数据可算” 报错。 -
数据裁剪:
filterBounds(roi)是 “空间筛选”,仅保留与 ROI 有交集的影像(并非像素级裁剪,像素级裁剪需后续clip(roi)),避免加载全球数据导致内存占用过高。 -
校验逻辑:
ghsl100.size():输出影像数量(如 10 代表包含 10 个年份的数据),若为 0,说明 ROI 范围内无该数据集覆盖(如高纬度无人区),需检查数据集版本或 ROI 范围;ghsl100.aggregate_array('system:index'):输出各影像的年份索引(如["2000", "2005", "2010"]),明确可用年份,避免后续计算时调用不存在的年份;ghsl100.first():输出首张影像的元数据,关键查看system:time_start(时间戳,用于后续提取年份)、crs(投影坐标系,如EPSG:4326)、bands(波段信息,确认built_surface波段存在)。
(三)模块 2:地图可视化 —— 年度建成区空间分布展示
核心作用:将各年份建成区影像添加到 GEE 地图界面,支持手动切换图层查看空间变化,同时通过可视化参数调整,让数据差异更直观。
// ------------- 2. 在地图上添加每年图层(默认隐藏) -------------
// 可视化参数:需根据 ROI 内数据实际范围调整
var visParams = {min: 0, max: 10000, palette: ['ffffff','c7e9b4','7fcdbb','41b6c4','225ea8']};// 客户端循环添加图层(数据集年份少,安全使用)
var ghslList = ghsl100.toList(ghsl100.size()); // 转为列表便于遍历
var n = ghsl100.size().getInfo(); // 获取影像数量(客户端变量)for (var i = 0; i < n; i++) {var img = ee.Image(ghslList.get(i)); // 提取单幅影像var time = ee.Date(img.get('system:time_start')).format('YYYY').getInfo(); // 提取年份Map.addLayer(img.clip(roi), visParams, 'GHSL_100m_' + time, false); // 添加图层
}Map.layers().get(0).setShown(true); // 首张影像默认可见
-
可视化参数(
visParams):决定影像在地图上的显示效果,是可视化的核心,需根据built_surface波段的实际数值范围调整:min: 0:最小值(建成区面积 / 比例为 0,对应无建成区区域);max: 10000:最大值(若built_surface是 “每像元面积(m²)”,100 米像元的最大面积为 100*100=10000 m²,符合逻辑;若后续诊断发现是 “比例值”,需改为max: 1);palette:颜色梯度,从白色(0)到深蓝色(10000),数值越高颜色越深,便于区分建成区密度(颜色越深,建成区越密集)。若颜色对比不明显,可替换为['white','yellow','orange','red','black']等强对比色。
-
客户端循环(
for循环):- 为何用客户端循环?GHSL 数据集年度影像数量少(通常 5-15 幅),
getInfo()不会导致客户端过载;若数据集影像数量多(如 Landsat 30 年数据),需改用服务器端map循环,避免客户端卡顿; img.clip(roi):像素级裁剪,仅保留 ROI 范围内的像元,避免影像超出研究区域导致视觉干扰;Map.addLayer(..., false):false表示图层默认隐藏,避免 10 个年份的图层叠加显示,导致地图混乱;最后通过Map.layers().get(0).setShown(true)让首张影像默认可见,方便用户初始查看。
- 为何用客户端循环?GHSL 数据集年度影像数量少(通常 5-15 幅),
-
图层管理:添加后的图层会在 GEE 地图界面右侧 “图层” 面板显示,名称为 “GHSL_100m_年份”,用户可勾选 / 取消勾选切换不同年份的建成区分布,直观观察空间扩张 / 收缩趋势。
(四)模块 3:年度建成区面积计算 —— 双场景验证确保精度
核心作用:针对 GHSL 数据 built_surface 波段单位不明确的问题(可能是 “每像元面积(m²)” 或 “建成区比例(0-1)”),并行计算两种场景的年度建成区面积,通过对比验证结果可靠性,是代码的核心分析模块。
// ------------- 3. 计算每年建成面积(两种假设) -------------
var list = ghsl100.toList(ghsl100.size());
var indices = ee.List.sequence(0, ghsl100.size().subtract(1)); // 生成索引列表// 服务器端 map 循环:每幅影像生成一个包含面积信息的 Feature
var features = indices.map(function(i){var img = ee.Image(list.get(i));var year = ee.Date(img.get('system:time_start')).format('YYYY'); // 提取年份var scale = ee.Number(img.projection().nominalScale()); // 影像原生分辨率(100m)// 场景 A:假设 built_surface 是“每像元建成区面积(m²)”var sum_m2 = ee.Number(img.reduceRegion({reducer: ee.Reducer.sum(), // 求和减速器geometry: roi, // 计算范围:ROIscale: scale, // 计算分辨率:原生分辨率(避免重采样误差)maxPixels: 1e13 // 最大像元数:支持大范围计算(1e13 足够覆盖省级区域)}).values().get(0)); // 提取求和结果(values() 取字典值,get(0) 取第一个值)// 场景 B:假设 built_surface 是“建成区比例(0-1)”var sum_m2_from_fraction = ee.Number(img.multiply(ee.Image.pixelArea()) // 比例 * 像元实际面积(m²).reduceRegion({reducer: ee.Reducer.sum(),geometry: roi,scale: scale,maxPixels: 1e13}).values().get(0));// 返回 Feature:包含年份、两种场景的面积(m² 和 km²)、分辨率return ee.Feature(null, {'year': year,'sum_m2_assume_m2': sum_m2, // 场景 A 面积(m²)'area_km2_assume_m2': sum_m2.divide(1e6), // 场景 A 面积(km²,1km²=1e6 m²)'sum_m2_assume_fraction': sum_m2_from_fraction, // 场景 B 面积(m²)'area_km2_assume_fraction': sum_m2_from_fraction.divide(1e6), // 场景 B 面积(km²)'scale': scale});
});var yearFeatures = ee.FeatureCollection(features); // 转为 FeatureCollection 便于后续使用
print('年度面积计算结果(双场景):', yearFeatures); // 控制台输出,供用户校验
-
服务器端循环(
indices.map):- 为何不用客户端
for循环?面积计算涉及大量像元(100 米分辨率、省级 ROI 可能包含数百万像元),服务器端循环可利用 GEE 云端算力,避免客户端算力不足导致崩溃; ee.List.sequence(0, ghsl100.size().subtract(1)):生成从 0 到 “影像数量 - 1” 的索引列表(如影像数量为 5,索引为 [0,1,2,3,4]),确保每幅影像都被遍历。
- 为何不用客户端
-
核心计算函数(
reduceRegion):- 功能:对指定区域(
geometry: roi)内的像元值进行统计(此处用ee.Reducer.sum()求和),是 GEE 中区域统计的核心函数; - 关键参数
scale: scale:scale是影像原生分辨率(100 米),若改为其他值(如 30 米),GEE 会自动重采样,可能导致面积计算误差(重采样会改变像元值),因此必须使用原生分辨率; - 关键参数
maxPixels: 1e13:GEE 默认reduceRegion最大处理像元数为 1e8(约 100km×100km 100 米分辨率区域),若 ROI 范围大(如省级),需调大此值,否则会报错 “超出最大像元数”,1e13 足够覆盖全球范围。
- 功能:对指定区域(
-
双场景计算逻辑:
- 场景 A(直接求和):若
built_surface是 “每像元建成区面积(m²)”,则所有像元值求和即为 ROI 内总建成区面积(m²),除以 1e6 转换为 km²(更符合常用单位); - 场景 B(比例 × 面积):若
built_surface是 “建成区比例(0-1)”,则需先乘以像元实际面积(ee.Image.pixelArea(),返回每像元的地球表面积,单位 m²),再求和得到总建成区面积(m²),最后转换为 km²; - 为何要双场景?GHSL 数据集不同版本的
built_surface单位可能不同(如早期版本为比例,新版本为面积),若仅用单一场景,可能导致结果偏差(如将比例值直接求和,得到的 “面积” 会远小于实际值),双场景可通过后续 “数据诊断” 模块验证哪个场景符合实际。
- 场景 A(直接求和):若
-
输出 FeatureCollection:
yearFeatures是包含多个Feature的集合,每个Feature对应一个年份,属性包含 “年份”“两种场景的面积(m² 和 km²)”“计算分辨率”,用户可在 GEE 控制台 “控制台” 面板查看,对比两种场景的面积差异(如场景 A 面积为 1000 km²,场景 B 为 10 km²,明显场景 A 更合理)。
(五)模块 4:柱状图绘制 —— 年度面积变化趋势可视化
核心作用:将 yearFeatures 中的年度面积数据转换为柱状图,直观展示建成区面积随时间的变化趋势(如逐年增长、先增后减),比表格更易发现规律。
// ------------- 4. 绘制柱状图(默认用场景 A 数据) -------------
var chart = ui.Chart.feature.byFeature(yearFeatures, 'year', ['area_km2_assume_m2']).setChartType('ColumnChart') // 图表类型:柱状图.setOptions({title: 'GHSL 100m 建成区面积年度变化(km²)—— 场景 A:built_surface 为 m²',hAxis: {title: '年份', titleTextStyle: {fontSize: 12}}, // 横轴:年份vAxis: {title: '建成区面积(km²)', titleTextStyle: {fontSize: 12}}, // 纵轴:面积legend: {position: 'none'}, // 图例:隐藏(单指标无需图例)colors: ['1d6fa5'], // 柱子颜色:深蓝色barWidth: 0.6 // 柱子宽度:避免过宽或过窄});print(chart); // 控制台输出图表
-
图表生成函数(
ui.Chart.feature.byFeature):- 功能:基于 FeatureCollection 生成 “按特征(年份)统计” 的图表,是 GEE 中常用的时序图表函数;
- 参数
yearFeatures:数据源(包含年份和面积的 FeatureCollection); - 参数
'year':横轴(X 轴)数据,对应 Feature 的year属性; - 参数
['area_km2_assume_m2']:纵轴(Y 轴)数据,对应 Feature 的 “场景 A 面积(km²)” 属性,若要展示场景 B,替换为['area_km2_assume_fraction']即可。
-
图表配置(
setOptions):title:图表标题,需明确说明数据来源、场景,避免歧义;hAxis/vAxis:横轴 / 纵轴配置,title为轴标签,titleTextStyle调整字体大小(默认字体较小,12 号更易读);legend: {position: 'none'}:因仅展示一个指标(场景 A 面积),图例无意义,隐藏后更简洁;若同时展示两个场景(如['area_km2_assume_m2', 'area_km2_assume_fraction']),需保留图例(position: 'right'),并在colors中添加第二种颜色(如['1d6fa5', 'ff7f0e']);barWidth: 0.6:柱子宽度(0-1 之间),0.6 可避免柱子过密(年份多时有重叠)或过疏(年份少时显空旷)。
-
图表交互:在 GEE 控制台查看图表时,鼠标悬停在柱子上会显示 “年份 + 面积” 的具体数值,便于精确读取;若需下载图表,可右键点击图表选择 “Save image as” 保存为 PNG 格式。
(六)模块 5:CSV 表格导出 —— 结果离线存储与二次分析
核心作用:将 yearFeatures 中的年度面积数据导出为 CSV 格式,存储到 Google Drive,方便用户用 Excel、Python(Pandas)、R 等工具进行离线分析(如趋势拟合、与其他数据关联)。
// ------------- 5. 导出表格到 Drive(CSV) -------------
Export.table.toDrive({collection: yearFeatures, // 导出数据源:年度面积 FeatureCollectiondescription: 'GHSL_100m_yearly_area_table', // 任务描述(在 Tasks 面板显示)folder: driveFolder, // 存储文件夹:模块 0 定义的 driveFolderfileNamePrefix: 'GHSL_100m_yearly_area_table', // 文件名前缀(避免重复)fileFormat: 'CSV' // 导出格式:CSV(通用表格格式)
});
| 参数名 | 含义与要求 | 注意事项 |
|---|---|---|
collection | 必须是 FeatureCollection 类型,此处为 yearFeatures(包含所有分析结果) | 若误传为 ImageCollection,会报错 “不是表格类型”;需确保 FeatureCollection 中无空值(如某年份面积计算失败,sum_m2 为 null,导出后 CSV 中对应单元格为空白,需后续处理) |
description | GEE Tasks 面板中显示的任务名称,需简洁明了,便于区分多个导出任务 | 若同时导出多个表格,需添加差异化后缀(如 GHSL_100m_yearly_area_table_2000_2020) |
folder | 存储文件夹,必须与模块 0 定义的 driveFolder 一致,避免文件分散存储 | 若文件夹不存在,GEE 会自动创建,但需确保 Google Drive 有足够权限(如未登录 Drive,导出会失败) |
fileNamePrefix | 导出文件的名称前缀,最终文件名会在后缀添加随机字符串(如 GHSL_100m_yearly_area_table_20240520.csv),避免同名文件覆盖 | 建议添加时间戳(如 fileNamePrefix: 'GHSL_100m_yearly_area_table_' + ee.Date(Date.now()).format('YYYYMMDD').getInfo()),确保每次导出文件唯一 |
fileFormat | 导出格式,支持 CSV、GeoJSON、KML 等,此处选 CSV(通用,支持多数分析工具) | 若需在 GIS 软件(如 ArcGIS)中使用,可改为 GeoJSON,但需注意 GeoJSON 包含空间信息(此处 Feature 无空间信息,仅为表格数据,CSV 更合适) |
- 运行代码后,在 GEE 界面右上角 “Tasks” 面板会出现一个名为 “GHSL_100m_yearly_area_table” 的任务;
- 点击任务右侧的 “RUN” 按钮,在弹出的对话框中确认参数(无需修改),点击 “RUN”;
- 任务状态从 “READY” 变为 “RUNNING”,完成后变为 “COMPLETED”;
- 打开 Google Drive,进入
driveFolder文件夹,即可找到导出的 CSV 文件。
(七)模块 6:GeoTIFF 影像批量导出 —— 空间数据离线使用
核心作用:将各年份的建成区影像(经 ROI 裁剪后)批量导出为 GeoTIFF 格式(GIS 通用影像格式),存储到 Google Drive,方便用户在 ArcGIS、QGIS 等软件中进行空间分析(如叠加分析、缓冲区分析)。
// ------------- 6. 批量导出每年影像(示例) -------------
var size = ghsl100.size().getInfo(); // 影像数量(客户端变量)
var clientList = ghsl100.toList(size).getInfo(); // 客户端影像列表(包含影像 ID)for (var i = 0; i < clientList.length; i++) {var imgId = clientList[i].id; // 提取影像 ID(如 "JRC/GHSL/P2023A/GHS_BUILT_S/2020")var img = ee.Image(imgId); // 通过 ID 构造 ee.Image 对象var year = ee.Date(img.get('system:time_start')).format('YYYY').getInfo(); // 提取年份// 导出任务配置Export.image.toDrive({image: img.clip(roi).toFloat(), // 导出影像:ROI 裁剪 + 转为浮点型(保留精度)description: 'GHSL_100m_' + year + '_ROI', // 任务描述(含年份,便于区分)folder: driveFolder, // 存储文件夹fileNamePrefix: 'ghsl_100m_' + year + '_ROI', // 文件名前缀(含年份)region: roi, // 导出范围:ROI(需为 Polygon 或 MultiPolygon,避免导出全图)scale: 100, // 导出分辨率:100米(与数据集原生分辨率一致)maxPixels: 1e13, // 最大像元数:支持大范围导出crs: img.projection().crs() // 导出坐标系:与影像原生坐标系一致(避免投影误差)});
}
-
客户端循环批量导出:
- 为何用客户端
for循环?Export.image.toDrive是 “任务生成函数”,必须在客户端执行(服务器端无法生成本地任务),且 GHSL 影像数量少(5-15 幅),循环效率高; clientList = ghsl100.toList(size).getInfo():将 ImageCollection 转为客户端列表,每个元素是影像的元数据字典(包含id、bands等),通过clientList[i].id提取影像 ID,再用ee.Image(imgId)构造影像对象(避免直接在循环中使用ghslList.get(i),客户端无法识别服务器端对象)。
- 为何用客户端
-
导出影像处理(
image: img.clip(roi).toFloat()):img.clip(roi):像素级裁剪,仅导出 ROI 范围内的影像,减少文件体积(如 ROI 是城市,导出文件仅几十 MB;若导出全图,可能达数 GB);toFloat():将影像数据类型转为浮点型(Float32),保留built_surface波段的原始精度(避免用toInt()导致小数部分丢失,如比例值 0.5 转为整数 0,数据失真)。
-
关键导出参数:
region: roi:导出范围,必须与img.clip(roi)一致,若region范围大于clip范围,导出影像仍为clip后的范围,但会浪费时间;若region范围小于clip范围,会导致影像被二次裁剪,数据丢失;scale: 100:导出分辨率,必须与数据集原生分辨率一致(100 米),若改为 30 米,GEE 会自动重采样,影像文件体积增大,且数据精度无提升(原始数据仅 100 米分辨率);crs: img.projection().crs():导出坐标系,与影像原生坐标系一致(如EPSG:4326),避免因坐标系转换导致空间位置偏移(如在 QGIS 中叠加其他 EPSG:4326 数据时无法对齐);maxPixels: 1e13:与模块 3 同理,避免因像元过多导致导出失败。
-
导出注意事项:
- 文件体积:100 米分辨率、100km×100km 的 ROI 影像体积约为 40MB(Float32 类型,单波段),省级 ROI 可能达数百 MB,需确保 Google Drive 有足够存储空间(免费 Drive 空间为 15GB,若导出 30 幅省级影像,可能超出空间);
- 任务启动:批量导出会在 Tasks 面板生成多个任务(如 10 个年份生成 10 个任务),可点击面板顶部的 “RUN ALL” 一键启动所有任务,无需逐个点击;
- 任务优先级:GEE 对免费用户的导出任务有优先级限制,若同时启动大量任务,可能会排队等待(有时需几小时完成),建议错峰导出(如夜间)。
(八)模块 7:数据单位诊断 —— 验证双场景合理性
核心作用:通过统计 built_surface 波段在 ROI 内的最小值、最大值、均值,判断该波段的实际单位(是 “面积(m²)” 还是 “比例(0-1)”),从而确定模块 3 中哪个场景的面积计算结果更可靠,是代码的 “质量控制模块”。
// ------------- 7. 额外诊断(判断 built_surface 单位)-------------
var sampleStats = ghsl100.map(function(img){// 统计 ROI 内 built_surface 波段的 min/max/meanvar stats = img.reduceRegion({reducer: ee.Reducer.minMax().combine(ee.Reducer.mean(), '', true), // 组合减速器:min/max/meangeometry: roi,scale: img.projection().nominalScale(),maxPixels: 1e13});// 返回 Feature:包含年份和统计结果return ee.Feature(null, stats).set('year', ee.Date(img.get('system:time_start')).format('YYYY'));
});print('年度 built_surface 统计(min/max/mean):', sampleStats); // 控制台输出// 诊断规则(用户需手动判断):
// 1. 若 min/max 均在 0-1 之间 → 大概率是“比例(0-1)”,选择场景 B 面积;
// 2. 若 max 接近 10000(100米像元面积) → 大概率是“面积(m²)”,选择场景 A 面积;
// 3. 若 max 远超 10000(如 1e5) → 数据异常,需检查数据集版本或波段选择。
-
组合减速器(
ee.Reducer.minMax().combine(...)):ee.Reducer.minMax():统计像元值的最小值(min)和最大值(max);ee.Reducer.mean():统计像元值的均值(mean);combine(..., '', true):将两个减速器的结果组合为一个字典(如{min: 0, max: 9800, mean: 1200}),true表示允许结果中存在重复键(此处无重复,仅为兼容);- 为何统计这三个值?最小值可判断是否有负数值(正常应为 0,负数值表示数据异常),最大值可判断单位范围(0-1 或 0-10000),均值可辅助验证(比例的均值通常在 0.1-0.5 之间,面积的均值通常在 100-5000 m² 之间)。
-
诊断规则应用示例:
- 示例 1:统计结果为
min: 0, max: 0.85, mean: 0.32→ 符合 0-1 范围,判断为 “比例”,后续分析应使用场景 B 的面积数据; - 示例 2:统计结果为
min: 0, max: 9950, mean: 1520→ 最大值接近 10000(100 米像元面积),判断为 “面积(m²)”,后续分析应使用场景 A 的面积数据; - 示例 3:统计结果为
min: -10, max: 12000, mean: 3000→ 存在负数值,数据异常,需检查是否选择了正确的波段(如误选built_surface_qc质量控制波段)或数据集版本是否兼容。
- 示例 1:统计结果为
-
诊断结果的重要性:若忽略此模块,直接使用错误场景的面积数据,会导致分析结果完全错误(如将比例值直接求和,得到的 “面积” 仅为实际值的 1/10000,无法反映真实建成区变化),因此必须先完成诊断,再选择合理的场景数据。
三、代码运行流程与常见问题解决方案
完整运行流程:
- 准备数据:在 GEE 资产面板导入 ROI 矢量数据,命名为 “table”(或修改代码中
roi变量为实际资产名); - 修改参数:在模块 0 中修改
driveFolder为自定义的 Google Drive 文件夹名; - 运行代码:点击 GEE 代码编辑器顶部的 “Run” 按钮,执行代码;
- 校验数据:查看控制台输出,确认数据集影像数量 > 0、年度面积计算结果无空值、诊断结果符合单位逻辑;
- 启动导出:在 Tasks 面板启动 CSV 表格和 GeoTIFF 影像导出任务;
- 离线分析:导出完成后,从 Google Drive 下载文件,用 Excel/Python/QGIS 进行后续分析。
常见问题与解决方案:
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 代码运行后控制台报错 “roi is not defined” | 未导入 ROI 矢量数据,或数据名称不是 “table” | 1. 在 GEE 资产面板导入矢量数据;2. 若数据名为 “my_roi”,修改代码 var roi = ee.FeatureCollection("users/xxx/my_roi") |
数据集影像数量为 0(ghsl100.size() 输出 0) | ROI 范围无该数据集覆盖(如高纬度无人区),或数据集版本错误 | 1. 缩小 ROI 范围(如选择城市区域);2. 更换数据集版本(如从 2023 版改为 2021 版);3. 检查数据集 ID 是否正确(如少写 “A” 导致 JRC/GHSL/P2023/GHS_BUILT_S 不存在) |
reduceRegion 报错 “Too many pixels” | maxPixels 值过小,ROI 范围大导致像元数超出限制 | 将 maxPixels 从 1e8 改为 1e13(或更大,如 1e14),确保覆盖 ROI 所有像元 |
| 导出任务一直处于 “RUNNING” 状态(超过 2 小时) | GEE 免费用户任务优先级低,或导出影像范围过大、分辨率过高 | 1. 错峰导出(如夜间);2. 缩小 ROI 范围(如分区域导出);3. 确认导出分辨率为 100 米,未误设为 30 米 |
| 导出的 GeoTIFF 影像在 QGIS 中显示为空白 | 1. 影像坐标系与 QGIS 画布坐标系不一致;2. 影像像元值范围与可视化参数不匹配 | 1. 在 QGIS 中右键影像→“Set CRS”→选择与影像一致的 CRS(如 EPSG:4326);2. 调整 QGIS 图层样式,将 “最小值 / 最大值” 改为诊断模块得到的 min/max 值 |
| 年度面积计算结果为 null | ROI 范围内无建成区(如荒漠区域),或 reduceRegion 计算失败 | 1. 扩大 ROI 范围,包含有建成区的区域;2. 检查 scale 参数是否为影像原生分辨率,避免重采样导致无数据 |
四、总结
本代码是一套完整的 GHSL 建成区数据分析流程,从数据加载到结果导出,每个模块都有明确的功能和逻辑,同时通过 “双场景计算” 和 “数据诊断” 确保结果可靠性。用户需重点关注:
- 数据校验:运行代码后先查看控制台输出,确认数据集、面积计算、诊断结果无异常;
- 单位判断:必须通过模块 7 的诊断结果,选择合理的面积计算场景;
- 导出控制:批量导出影像前,确认 Google Drive 空间足够,避免任务失败。
通过本代码,用户可快速量化研究区域内建成区的年度变化特征,为城市规划、土地利用监测、生态环境评估等领域提供数据支撑。
五、运行结果
若觉得代码对您的研究 / 项目有帮助,欢迎点击打赏支持!需要完整代码的朋友,打赏后可在后台私信(复制文章标题发给我),我会尽快发您完整可运行代码,感谢支持!
