基于 GEE 利用 WorldPop 数据集批量导出 100 米分辨率人口影像数据与时序分析
目录
一、研究区域与地图初始化
二、影像裁剪函数定义
三、WorldPop 数据集导入与预处理
四、2020 年人口数据可视化
五、2000-2020 年人口动态变化图表
六、影像导出函数定义
七、批量导出影像
八、运行结果

若觉得代码对您的研究 / 项目有帮助,欢迎点击打赏支持!需要完整代码的朋友,打赏后可在后台私信(复制文章标题发给我),我会尽快发您完整可运行代码,感谢支持!
本代码基于 Google Earth Engine(GEE)平台,以中国区域为研究范围,完成 WorldPop 100 米分辨率人口数据集从数据筛选、空间裁剪、年度数据提取、可视化呈现、时序分析到批量导出的全流程处理,最终实现 2000-2020 年人口分布静态展示与动态变化量化分析,同时生成可用于后续 GIS 分析的 GeoTIFF 格式数据。
一、研究区域与地图初始化
var geometry = table;
Map.centerObject(geometry, 8);
-
var geometry = table;- 作用:定义研究区域的空间边界,是后续所有空间操作(裁剪、统计、导出)的核心基准。
- 关键前提:
table并非代码中定义的变量,而是提前导入 GEE 的矢量边界数据(通常为 Shapefile、KML 或 Fusion Table 格式),需包含研究区域的面状几何信息(如中国省级 / 市级行政边界)。若未导入或table格式错误,后续所有依赖geometry的操作(如裁剪、导出)都会失效。 - 数据本质:
geometry在 GEE 中属于ee.Geometry类型,存储了区域的经纬度坐标串,是连接影像数据与空间范围的 “桥梁”。
-
Map.centerObject(geometry, 8);- 作用:自动调整 GEE 地图窗口的视野,确保研究区域完整、清晰地显示在画布中央。
- 参数解读:
- 第一个参数
geometry:指定地图定位的 “目标对象”,GEE 会计算该几何对象的中心点,将其作为地图视野中心; - 第二个参数
8:代表地图缩放级别(GEE 缩放级范围为 0-24,数值越小视野越广,数值越大细节越清晰)。缩放级 8 对应的空间范围约为 “省级行政区全域”,若研究区域为市级,可将数值调整为 10-12;若为国家级,可调整为 6-7。
- 第一个参数
- 实际效果:运行后无需手动拖动 / 缩放地图,直接定位到目标区域,提升操作效率。
二、影像裁剪函数定义
var clipToCol = function(image) {return image.clip(geometry);
};
- 函数本质:这是一个自定义的影像处理函数,属于 GEE 中典型的 “单景影像输入 - 单景影像输出” 模式,用于批量剔除影像中研究区域外的无效数据。
- 参数与返回值:
- 输入参数
image:代表传入的单景ee.Image类型数据(即 WorldPop 数据集中的某一年份人口影像); - 返回值
image.clip(geometry):通过clip()方法对输入影像进行空间裁剪,仅保留geometry边界内的像素,边界外像素会被设为 “无数据”(NoData)。
- 输入参数
- 为何单独定义函数:WorldPop 数据集为全球范围影像,若直接对影像集处理,需重复编写裁剪逻辑;定义函数后,可通过
map()方法一次性对整个影像集批量裁剪,减少代码冗余,提升可维护性。 - 潜在注意事项:若
geometry边界存在拓扑错误(如自相交、边界不闭合),clip()方法可能返回空白影像,需提前在 ArcGIS 或 QGIS 中检查并修复矢量边界。
三、WorldPop 数据集导入与预处理
var worldpop = ee.ImageCollection("WorldPop/GP/100m/pop").filterBounds(geometry).map(clipToCol).filter(ee.Filter.eq('country', 'CHN')).select('population');
print("WorldPop影像集", worldpop);
-
数据集导入:
ee.ImageCollection("WorldPop/GP/100m/pop")- 数据集背景:WorldPop(World Population)是由南安普顿大学等机构构建的全球高分辨率人口数据集,GEE 中提供的
WorldPop/GP/100m/pop版本为100 米分辨率,数据类型为 “人口密度”(单位:人 / 像素,需结合像素面积计算实际人口数),时间跨度覆盖 2000-2020 年(每年 1 景影像)。 - 数据类型:
ee.ImageCollection(影像集),即由多景ee.Image(单景影像)组成的集合,后续需通过筛选、聚合等操作提取单景或多景目标影像。
- 数据集背景:WorldPop(World Population)是由南安普顿大学等机构构建的全球高分辨率人口数据集,GEE 中提供的
-
空间初筛:
.filterBounds(geometry)- 作用:从全球影像集中筛选出 “与研究区域有空间交集” 的影像,大幅减少后续处理的数据量(避免加载全球无关影像导致运算卡顿)。
- 筛选逻辑:GEE 会判断每景影像的 “空间范围”(
ee.Image.geometry())是否与geometry有重叠,仅保留重叠的影像。例如,若geometry为中国边界,会筛选出覆盖中国区域的所有 WorldPop 影像(实际为 2000-2020 年每年 1 景,共 21 景)。 - 与
clip()的区别:filterBounds()是 “筛选影像集”(保留整景影像),clip()是 “裁剪单景影像”(保留影像中的部分区域),二者为 “先筛选、后裁剪” 的逻辑,前者减少影像数量,后者减少单景影像的数据量。
-
批量裁剪:
.map(clipToCol)- 作用:调用第 2 步定义的
clipToCol函数,对filterBounds筛选后的每景影像进行空间裁剪。 - 执行逻辑:
map()是 GEE 中影像集处理的核心方法,会 “遍历影像集中的每景影像,将函数应用于单景影像,最终返回新的影像集”。例如,某景覆盖 “中国 + 周边国家” 的影像,经clipToCol处理后,仅保留中国境内的像素,周边国家像素设为 NoData。
- 作用:调用第 2 步定义的
-
国家筛选:
.filter(ee.Filter.eq('country', 'CHN'))- 作用:通过影像的 “元数据” 筛选出中国专属的人口影像,避免因
geometry边界不完整导致的非中国区域影像残留。 - 元数据背景:WorldPop 影像集中的每景影像都包含
country元数据(存储国家 ISO 代码),中国对应的代码为CHN,其他国家如美国为USA、印度为IND。 - 筛选逻辑:
ee.Filter.eq(key, value)表示 “筛选元数据中key等于value的影像”,此处即保留country元数据为CHN的影像,进一步确保数据区域准确性(即使geometry边界有误差,也能通过元数据排除非中国影像)。
- 作用:通过影像的 “元数据” 筛选出中国专属的人口影像,避免因
-
波段选择:
.select('population')- 作用:从影像中提取 “人口数据波段”,剔除其他无关波段,简化数据结构。
- 波段背景:WorldPop 影像可能包含多个波段(如人口密度波段、数据质量评估波段等),其中
population波段是核心,存储的是 “每 100 米像素对应的人口数量”(注意:并非人口密度,需结合像素面积(100m*100m=10000㎡)计算人口密度,即人口密度 = 像素人口数 / 10000 人 /㎡)。 - 必要性:若不筛选波段,后续分析(如
mean()、sum())可能误将非人口波段纳入计算,导致结果错误;仅保留目标波段也能减少数据存储和运算压力。
-
数据查看:
print("WorldPop影像集", worldpop)- 作用:在 GEE 控制台的 “Console” 面板输出处理后的影像集信息,用于验证数据是否正确。
- 输出内容:点击控制台中的影像集名称,可查看影像数量(2000-2020 年共 21 景)、每景影像的时间(
system:time_start)、元数据(country、resolution等)、波段信息(population波段的最小值、最大值等)。 - 验证要点:需确认影像数量是否为 21 景、
country元数据是否均为CHN、population波段是否存在,若有异常(如影像数量为 0),需检查table边界是否正确、数据集 ID 是否拼写错误(如误写为WorldPop/GP/30m/pop)。
四、2020 年人口数据可视化
var start = ee.Date.fromYMD(2020, 1, 1);
var end = ee.Date.fromYMD(2020, 12, 31);
var worldpop2020 = ee.Image(worldpop.filterDate(start, end).mean());
worldpop2020 = worldpop2020.clip(geometry);
Map.addLayer(worldpop2020, {min: 0,max: 100,palette: ['24126c', '1fff4f', 'd4ff50']
}, "population 2020");
-
时间范围定义:
ee.Date.fromYMD(2020, 1, 1)与ee.Date.fromYMD(2020, 12, 31)- 作用:创建 GEE 中的
ee.Date类型时间对象,定义 2020 年的完整时间范围(从 1 月 1 日 00:00 到 12 月 31 日 23:59),用于筛选 2020 年的人口影像。 - 时间格式:
fromYMD(year, month, day)是 GEE 中创建日期的常用方法,需严格按照 “年 - 月 - 日” 顺序传入整数参数(如ee.Date.fromYMD(2020, 2, 29)可正确识别闰年 2 月 29 日)。 - 替代写法:也可使用
ee.Date('2020-01-01')直接传入字符串格式日期,但fromYMD更便于通过变量动态调整年份(如var year = 2020; ee.Date.fromYMD(year, 1, 1))。
- 作用:创建 GEE 中的
-
2020 年影像提取:
worldpop.filterDate(start, end).mean()- 步骤 1:
filterDate(start, end)—— 从预处理后的影像集中筛选出 “时间落在start和end之间” 的影像。由于 WorldPop 数据集为 “每年 1 景”,此处会筛选出 2020 年的 1 景影像(若数据集存在季度或月度数据,会筛选出多景)。 - 步骤 2:
.mean()—— 对筛选后的影像集计算 “像素级平均值”。此处因仅 1 景影像,mean()的作用是将ee.ImageCollection(影像集)转换为ee.Image(单景影像),避免后续Map.addLayer因数据类型不匹配报错(Map.addLayer仅支持单景影像或矢量数据,不直接支持影像集)。 - 关键转换:
ee.Image(...)—— 显式将mean()返回的影像对象转换为ee.Image类型,确保数据类型一致性(部分情况下mean()返回的是ee.ComputedObject,需显式转换)。
- 步骤 1:
-
二次裁剪:
worldpop2020.clip(geometry)- 作用:对提取的 2020 年影像进行 “二次裁剪”,进一步确保影像无区域外冗余数据。
- 必要性:虽然第 3 步已对影像集批量裁剪,但可能因
filterBounds或filter筛选不彻底,导致影像边缘存在少量非研究区域像素;二次裁剪可彻底清除这些像素,保证可视化结果的空间准确性。
-
地图添加与可视化配置:
Map.addLayer(...)- 作用:将 2020 年人口影像添加到 GEE 地图窗口,通过颜色差异直观展示人口分布差异。
- 可视化参数详解:
参数 取值 作用与逻辑 min0 定义颜色映射的 “最小值阈值”—— 像素人口数≤0 时,显示配色方案的第一种颜色(深蓝)。 max100 定义颜色映射的 “最大值阈值”—— 像素人口数≥100 时,显示配色方案的最后一种颜色(浅黄)。 palette['24126c','1fff4f','d4ff50'] 定义颜色渐变方案:深蓝(低人口)→亮绿(中人口)→浅黄(高人口),符合 “低数值冷色、高数值暖色” 的视觉习惯,便于快速识别人口密集区。 最后参数 "population 2020" 定义图层名称,显示在地图窗口右上角的 “图层列表” 中,便于区分不同图层(如后续添加 2010 年图层可命名为 “population 2010”)。 - 效果验证:添加后,地图上人口密集的城市区域(如北京、上海)会显示为浅黄,人口稀少的山区会显示为深蓝,直观呈现 2020 年研究区域的人口空间分布格局。
五、2000-2020 年人口动态变化图表
var chart = ui.Chart.image.seriesByRegion({imageCollection: worldpop,regions: geometry,reducer: ee.Reducer.sum(),scale: 100,xProperty: 'system:time_start'
})
.setSeriesNames(['population'])
.setOptions({title: '人口动态变化',hAxis: {title: '年份',titleTextStyle: {italic: false, bold: true}},vAxis: {title: '总人口',titleTextStyle: {italic: false, bold: true}},lineWidth: 5,colors: ['e37d05'],curveType: 'function'
});
print(chart);
-
图表创建核心:
ui.Chart.image.seriesByRegion(...)- 函数功能:GEE 内置的时序图表生成函数,用于计算 “指定区域内影像集的统计指标随时间的变化”,并生成交互式折线图。
- 核心参数详解:
参数 取值 作用与逻辑 imageCollectionworldpop 指定数据源 —— 即预处理后的 2000-2020 年中国人口影像集。 regionsgeometry 指定统计区域 —— 即研究区域,函数会计算该区域内所有像素的统计值(此处为总人口)。 reduceree.Reducer.sum() 指定统计方法 —— sum()表示 “像素值求和”,即对geometry内所有population波段像素值求和,得到研究区域的 “总人口数”(因population波段已为 “每像素人口数”,求和直接为总人口)。若需计算平均人口密度,可改用ee.Reducer.mean()。scale100 指定统计尺度 —— 单位为米,需与数据集分辨率一致(WorldPop 为 100 米)。若设置为 200 米,GEE 会先将影像重采样到 200 米,再计算统计值,可能导致结果误差;若设置过小(如 30 米),会增加运算时间且无精度提升。 xProperty'system:time_start' 指定 X 轴(时间轴)的数据源 —— system:time_start是 GEE 影像集中每景影像的默认时间元数据,存储影像的 “起始时间”(WorldPop 影像的system:time_start通常为每年 1 月 1 日 00:00),函数会自动将其转换为 “年份” 显示在 X 轴。
-
图表系列命名:
setSeriesNames(['population'])- 作用:定义图表中 “数据系列” 的名称,显示在图表图例中。此处仅 1 个数据系列(总人口),命名为
population,若统计多个区域(如多个省份),可传入多个名称(如['北京', '上海', '广州'])。 - 必要性:若不设置,图例默认显示为 “Series 0”,不便于识别数据含义。
- 作用:定义图表中 “数据系列” 的名称,显示在图表图例中。此处仅 1 个数据系列(总人口),命名为
-
图表样式配置:
setOptions(...)title: '人口动态变化':图表总标题,显示在图表顶部中央,直观说明图表主题。hAxis(水平轴,X 轴):title: '年份':X 轴标题,说明 X 轴数据含义;titleTextStyle: {italic: false, bold: true}:X 轴标题样式 —— 非斜体(italic: false)、加粗(bold: true),增强视觉突出度。
vAxis(垂直轴,Y 轴):title: '总人口':Y 轴标题,说明 Y 轴数据含义(单位隐含为 “人”);titleTextStyle:与 X 轴一致,确保样式统一。
lineWidth: 5:折线宽度 —— 单位为像素,设置为 5 可使折线更粗,避免因图表缩放导致线条模糊。colors: ['e37d05']:折线颜色 —— 采用十六进制颜色码(e37d05为橙色),若有多个数据系列,可传入多个颜色码(如['e37d05', '2e86ab', 'a23b72'])。curveType: 'function':折线类型 ——function表示 “平滑曲线”,使时序趋势更直观;若需显示 “折线”(拐点清晰),可改为curveType: 'none'。
-
图表输出:
print(chart)- 作用:在 GEE 控制台的 “Console” 面板输出交互式图表,可进行以下操作:
- 鼠标悬停在折线上,查看具体年份的 “总人口数”(如悬停在 2020 年,显示 “2020: 1400000000”);
- 点击图表右上角的 “下载” 按钮,将图表导出为 PNG(图片)或 CSV(数据表格)格式,用于报告撰写或后续数据分析;
- 拖动图表边缘调整大小,或通过 “缩放” 按钮放大某段时间的趋势(如放大 2010-2020 年的变化)。
- 结果解读:正常情况下,图表应呈现 “2000-2020 年研究区域总人口先增长、后趋于稳定” 的趋势(符合中国人口变化实际),若出现异常波动(如某一年总人口骤降),需检查
reducer是否正确、geometry是否完整。
- 作用:在 GEE 控制台的 “Console” 面板输出交互式图表,可进行以下操作:
六、影像导出函数定义
function exportImage(image, region, fileName) {Export.image.toDrive({image: image,description: fileName,fileNamePrefix: fileName,folder: "population",scale: 100,region: geometry,maxPixels: 1e13,fileFormat: "GeoTIFF",crs: "EPSG:4326"});
}
-
函数定义与参数
- 函数名称:
exportImage—— 直观说明函数功能(导出影像)。 - 输入参数:
image:待导出的单景ee.Image类型数据(如 2020 年人口影像);region:导出区域(此处代码中实际使用的是geometry,参数region未真正生效,属于代码小瑕疵,优化后可改为region: region);fileName:导出文件的名称前缀,用于区分不同年份的影像。
- 函数名称:
-
导出核心方法:
Export.image.toDrive(...)- 函数功能:GEE 中用于将影像导出到 “Google Drive” 的内置方法,需在 GEE 控制台手动触发 “运行任务” 才能执行导出(代码仅创建导出任务,不自动执行)。
- 关键导出参数解析(直接影响导出结果的准确性和可用性):
参数 取值 作用与逻辑 imageimage 指定待导出的影像 —— 即函数输入的 image参数,需确保为单景ee.Image类型。descriptionfileName 导出任务的名称,显示在 GEE “Tasks” 面板中,便于识别任务(如 “Worldpop-CHN-2020”)。 fileNamePrefixfileName 导出文件的名称前缀 ——Google Drive 中最终的文件名为 “前缀.tif”(如 “Worldpop-CHN-2020.tif”)。若需添加后缀(如 “_clip”),可改为 fileNamePrefix: fileName + "_clip"。folder"population" 指定 Google Drive 中的 “目标文件夹”—— 需提前在 Google Drive 中手动创建该文件夹(路径:Google Drive 首页→新建→文件夹→命名为 “population”)。若文件夹不存在,导出任务会失败,提示 “Folder not found”。 scale100 导出分辨率 —— 与数据集分辨率一致(100 米),确保导出影像的空间精度与原始数据一致。若需降低分辨率(如用于小尺度分析),可设置为 200 米或 500 米,减少文件体积。 regiongeometry 导出区域 —— 与研究区域一致,仅导出 geometry内的像素,避免导出无关区域导致文件过大。此处代码中参数region未使用函数输入的region变量,属于小问题,优化后可改为region: region,增强函数通用性。maxPixels1e13 最大像素限制 ——GEE 默认限制导出影像的像素数为 1e8(1 亿),若研究区域较大(如中国全域),100 米分辨率的像素数会远超 1e8(中国国土面积约 960 万平方公里,100 米分辨率像素数约 9.6e9),需将 maxPixels设置为更大值(如 1e13),避免导出任务因 “像素数超限” 失败。1e13 表示 “10 万亿像素”,远超一般研究区域的需求,可放心使用。fileFormat"GeoTIFF" 导出文件格式 ——GeoTIFF 是 GIS 领域通用的栅格数据格式,支持存储空间参考信息(坐标系、分辨率等),可直接在 ArcGIS、QGIS、ENVI 等软件中打开分析。若需导出为其他格式(如 JPEG),可改为 "JPEG",但 JPEG 不支持 NoData 值,不适合人口数据。crs: "EPSG:4326"导出坐标系 ——EPSG:4326 是 “WGS84 坐标系”,为全球通用的地理坐标系(经纬度坐标),适用于全球范围的空间分析。若研究区域需使用投影坐标系(如中国常用的 “CGCS2000 / 高斯 - 克吕格”),可改为对应的 EPSG 代码(如 "EPSG:4490"),但需确保投影坐标系与研究区域匹配。/
-
函数通用性
- 优势:该函数将影像导出的所有参数(除
image、region、fileName外)标准化,后续导出不同年份、不同区域的影像时,只需调用exportImage并传入不同参数,无需重复编写Export.image.toDrive的复杂配置,大幅提升代码复用性。 - 潜在优化:可在函数中添加 “数据类型转换”(如
image.int16()),避免每次调用前手动转换;或添加 “压缩参数”(如cloudOptimized: true),导出 “云优化 GeoTIFF”(COG),提升后续加载速度。
- 优势:该函数将影像导出的所有参数(除
七、批量导出影像
var indexList = worldpop.reduceColumns(ee.Reducer.toList(), ["system:index"]).get("list");
print("时间索引列表", indexList);
indexList.evaluate(function(indexs) {for (var i = 0; i < indexs.length; i++) {var image = worldpop.filter(ee.Filter.eq("system:index", indexs[i])).first().int16();exportImage(image, geometry, "Worldpop-CHN-" + indexs[i]);}
});
-
提取时间索引列表:
worldpop.reduceColumns(...)-
作用:从预处理后的影像集中提取每景影像的 “时间索引”(
system:index),生成一个列表,用于后续循环筛选每景影像。 -
关键方法解析:
reduceColumns(reducer, selectors):GEE 中用于 “对影像集的元数据进行统计” 的方法,不同于reduce(对影像像素值统计),reduceColumns仅处理元数据。reducer: ee.Reducer.toList():将筛选出的元数据转换为 “列表”(ee.List类型),此处即把所有影像的system:index元数据整合为一个列表。selectors: ["system:index"]:指定要提取的元数据字段 ——system:index是 GEE 影像集的默认索引元数据,WorldPop 影像的system:index格式为 “年份”(如2000、2001、…、2020),部分数据集可能为 “年份_月份”(如2020_01)。
.get("list"):reduceColumns返回的是一个ee.Dictionary(字典)对象,键为"list",值为system:index列表,通过get("list")提取出列表(ee.List类型),赋值给indexList。
-
输出验证:
print("时间索引列表", indexList)在控制台输出列表,正常情况下应显示为[2000, 2001, ..., 2020](共 21 个元素),若索引格式不符(如CHN_2000),需调整后续筛选逻辑(如filter(ee.Filter.stringEndsWith("system:index", indexs[i])))。
-
-
服务器端与客户端数据转换:
indexList.evaluate(...)-
核心背景:GEE 的数据处理分为 “服务器端” 和 “客户端”:
- 服务器端:
ee.List、ee.Image、ee.ImageCollection等 GEE 原生数据类型,存储在 GEE 服务器中,需通过 GEE 的方法(如filter、map)处理,无法直接在客户端(如 JavaScript 的for循环)中使用; - 客户端:JavaScript 原生数据类型,如
Array、Number、String等,可在本地使用for循环、if判断等逻辑处理。
- 服务器端:
-
evaluate方法作用:将服务器端的ee.List类型(indexList)转换为客户端的Array类型(indexs),为后续for循环批量处理提供条件。若不使用evaluate,直接对indexList进行for循环,会因数据类型不匹配报错(JavaScript 无法识别ee.List)。 -
执行逻辑:
indexList.evaluate(function(indexs) { ... })——evaluate是一个 “异步函数”,会先向 GEE 服务器发送请求,获取indexList的实际数据,转换为客户端Array后,再执行回调函数(function(indexs) { ... })中的逻辑。
-
-
循环筛选与数据转换:
for循环内部逻辑- 作用:通过
for循环遍历每个时间索引,筛选出对应的单景影像,并进行数据类型转换,为导出做准备。 for (var i = 0; i < indexs.length; i++):标准 JavaScriptfor循环,遍历客户端Array(indexs)的每个元素(即每个年份索引),i为循环变量,从 0 到indexs.length-1(共 21 次循环,对应 2000-2020 年)。worldpop.filter(ee.Filter.eq("system:index", indexs[i])):根据当前循环的时间索引(indexs[i]),从影像集中筛选出 “system:index等于indexs[i]” 的影像。例如,当i=0时,indexs[i] = 2000,筛选出 2000 年的人口影像(影像集)。.first():从筛选出的影像集中提取 “第一景影像”(因system:index唯一,筛选出的影像集仅 1 景),将ee.ImageCollection转换为ee.Image(单景影像),便于后续处理。.int16():将影像的数据类型转换为Int16(16 位有符号整数)。WorldPop 原始数据可能为Float32(32 位浮点数),转换为Int16的优势:- 减少文件体积:
Int16每个像素占 2 字节,Float32占 4 字节,转换后文件体积减半,便于存储和传输; - 避免浮点误差:人口数为整数,
Float32可能存在小数位(如 123.0),转换为Int16可去除小数位,确保数据准确性(需注意:若原始数据存在小数人口数,转换可能导致精度损失,但 WorldPop 数据已为整数,无此问题)。
- 减少文件体积:
- 作用:通过
-
批量调用导出函数:
exportImage(...)- 作用:对每景处理后的影像,调用第 6 步定义的
exportImage函数,生成导出任务。 - 参数传递:
image:当前循环筛选并转换后的单景影像(如 2000 年Int16类型影像);geometry:导出区域(即研究区域);fileName:导出文件名称,格式为 “Worldpop-CHN - 年份”(如Worldpop-CHN-2000),通过字符串拼接("Worldpop-CHN-" + indexs[i])生成,确保每个年份的文件名称唯一,避免导出时覆盖。
- 作用:对每景处理后的影像,调用第 6 步定义的
八、运行结果
若觉得代码对您的研究 / 项目有帮助,欢迎点击打赏支持!需要完整代码的朋友,打赏后可在后台私信(复制文章标题发给我),我会尽快发您完整可运行代码,感谢支持!
