Google Earth Engine:如何将LandTrendr输出数组保存为表格?
问题描述
基于LandTrendr算法提取土地覆被变化时,提取拟合值数组后,控制台执行print(fitted)仅显示“Image (1 Band)”,无法查看具体数值,需要将数组输出保存为表格格式。原代码参考LandTrendr官方文档的5.1 LandTrendr Band部分编写,代码如下:
var points = ee.Geometry.Point([-121.946741626287, 39.7895992866194]); // Define annual composite date range. var startDay = 175; // start at 175th day of year var nDays = 90; // end 120 days later // Define year range var startYear = 1990; var endYear = 2020; // Define band to use for segmentation var bandName = 'B7'; // Define LandTrendr parameters var ltParams = { maxSegments: 6, spikeThreshold: 0.9, vertexCountOvershoot: 3, preventOneYearRecovery: true, recoveryThreshold: 0.25, pvalThreshold: 0.05, bestModelProportion: 0.75, minObservationsNeeded: 6 }; // Display the point. Map.centerObject (points, 13); Map.addLayer(points, {color: 'red'}); Map.setOptions('SAtellite'); // Define function to mask clouds and cloud shadows. function cfmask(img) { var cloudShadowBitMask = 1 << 3; var cloudsBitMask = 1 << 5; var Mask = qa.bitweiseAnd (cloudShadowBitMask) .eq(0) .and(qa.bitwiseAnd(cloudsBitMask).eq(0)) return img.updateMask(mask); } // Import Landsat 5 surface reflectance collection var lsCol = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR'); // Define a list of years to make composits for. var yearsList = ee.List.sequence(startYear, endYear, 1); // Map over the year list to build an annual composite collection. var annualCol = ee.ImageCollection.fromImages( yearsList.map(function(yr) { var startDate = ee.Date.fromYMD(yr, 1, 1).advance(startDay, 'day'); var middleDate = startDate.advance(nDays/2, 'day'); var endDate = startDate.advance(nDays+1, 'day'); var yearCol = lsCol .filterDate(startDate, endDate) .filterBounds(points) .select(bandName) .median(); var nBands = yearCol.bandNames().size(); return yearCol.set({ 'system:time_start': middleDate.millis(), 'nBands': nBands }); }) ); // Deal with missing years (no images or all pixels masked). var yearPresentCol = annualCol.filter(ee.Filter.neq('nBands', 0)); var yearAbsentCol = annualCol.filter(ee.Filter.eq('nBands', 0)); // Make a filter image for missing years - all pixels masked. var dummyImg = ee.Image(0).selfMask().rename(bandName); // Add dummy image band to image with bands (missing years). yearAbsentCol = yearAbsentCol.map(function(img) { return img.addBands(dummyImg); }); // merge the missing years collection to valid years collection. var ltCol = yearPresentCol.merge(yearAbsentCol); // Set the annual composite collection as the LandTrendr timeSeries parameter. ltParams.timeSeries = ltCol; var ltArrImg = ee.Algorithms.TemporalSegmentation.LandTrendr(ltParams); print(ltArrImg); // Map.addLayer(ltArrImg); var segmentationInfo = ltArrImg.select(['LandTrendr']) var LTarray = ltArrImg.select(['LandTrendr']); // subset the LandTrendr segmentation info var year = LTarray.arraySlice(0, 0, 1); // slice out the year row var fitted = LTarray.arraySlice(0, 2, 3); // slice out the fitted values row print(fitted);
解决方案
问题核心
fitted是GEE中的数组图像(Array Image),控制台直接打印只会显示图像类型标识,不会解析并展开数组内的具体数值。需提取目标点位/区域的数值,转换为结构化格式后导出为表格。
步骤1:修正原代码错误
原代码的云掩膜函数存在变量未定义、拼写错误,先修正:
// 修正后的云掩膜函数 function cfmask(img) { var qa = img.select('pixel_qa'); // 补充定义qa变量 var cloudShadowBitMask = 1 << 3; var cloudsBitMask = 1 << 5; var mask = qa.bitwiseAnd(cloudShadowBitMask) // 修正拼写bitweiseAnd为bitwiseAnd,统一变量大小写 .eq(0) .and(qa.bitwiseAnd(cloudsBitMask).eq(0)); return img.updateMask(mask); }
步骤2:提取并结构化数值
将年份与拟合值数组合并后,提取目标点的数值并转换为表格结构:
// 合并年份与拟合值数组,展平为普通波段 var yearFitted = year.addBands(fitted).arrayFlatten([['year', 'fitted_value']]); // 提取目标点的数值 var pointData = yearFitted.sampleRegions({ collection: ee.FeatureCollection(points), scale: 30, // 匹配Landsat 30米分辨率 geometries: true }); // 打印结构化表格数据到控制台 print('年份-拟合值表格', pointData);
步骤3:导出为CSV表格
通过GEE的导出功能将数据保存到Google Drive,生成可编辑的表格:
// 导出到Google Drive Export.table.toDrive({ collection: pointData, description: 'LandTrendr_Fitted_Values', folder: 'GEE_Outputs', // 自定义Drive文件夹名称 fileFormat: 'CSV' });
完整修正代码
整合所有修正与新增逻辑后的完整代码:
var points = ee.Geometry.Point([-121.946741626287, 39.7895992866194]); // Define annual composite date range. var startDay = 175; // start at 175th day of year var nDays = 90; // end 120 days later // Define year range var startYear = 1990; var endYear = 2020; // Define band to use for segmentation var bandName = 'B7'; // Define LandTrendr parameters var ltParams = { maxSegments: 6, spikeThreshold: 0.9, vertexCountOvershoot: 3, preventOneYearRecovery: true, recoveryThreshold: 0.25, pvalThreshold: 0.05, bestModelProportion: 0.75, minObservationsNeeded: 6 }; // Display the point. Map.centerObject(points, 13); Map.addLayer(points, {color: 'red'}); Map.setOptions('SATELLITE'); // 修正拼写SAtellite为大写SATELLITE // 修正后的云掩膜函数 function cfmask(img) { var qa = img.select('pixel_qa'); var cloudShadowBitMask = 1 << 3; var cloudsBitMask = 1 << 5; var mask = qa.bitwiseAnd(cloudShadowBitMask) .eq(0) .and(qa.bitwiseAnd(cloudsBitMask).eq(0)); return img.updateMask(mask); } // Import Landsat 5 surface reflectance collection var lsCol = ee.ImageCollection('LANDSAT/LT05/C01/T1_SR') .map(cfmask); // 应用云掩膜 // Define a list of years to make composits for. var yearsList = ee.List.sequence(startYear, endYear, 1); // Map over the year list to build an annual composite collection. var annualCol = ee.ImageCollection.fromImages( yearsList.map(function(yr) { var startDate = ee.Date.fromYMD(yr, 1, 1).advance(startDay, 'day'); var middleDate = startDate.advance(nDays/2, 'day'); var endDate = startDate.advance(nDays+1, 'day'); var yearCol = lsCol .filterDate(startDate, endDate) .filterBounds(points) .select(bandName) .median(); var nBands = yearCol.bandNames().size(); return yearCol.set({ 'system:time_start': middleDate.millis(), 'nBands': nBands }); }) ); // Deal with missing years (no images or all pixels masked). var yearPresentCol = annualCol.filter(ee.Filter.neq('nBands', 0)); var yearAbsentCol = annualCol.filter(ee.Filter.eq('nBands', 0)); // Make a filter image for missing years - all pixels masked. var dummyImg = ee.Image(0).selfMask().rename(bandName); // Add dummy image band to image with bands (missing years). yearAbsentCol = yearAbsentCol.map(function(img) { return img.addBands(dummyImg); }); // merge the missing years collection to valid years collection. var ltCol = yearPresentCol.merge(yearAbsentCol); // Set the annual composite collection as the LandTrendr timeSeries parameter. ltParams.timeSeries = ltCol; var ltArrImg = ee.Algorithms.TemporalSegmentation.LandTrendr(ltParams); print('LandTrendr结果图像', ltArrImg); var LTarray = ltArrImg.select(['LandTrendr']); // subset the LandTrendr segmentation info var year = LTarray.arraySlice(0, 0, 1); // slice out the year row var fitted = LTarray.arraySlice(0, 2, 3); // slice out the fitted values row // ----------------新增代码:提取并导出表格---------------- // 合并年份与拟合值数组,展平为普通波段 var yearFitted = year.addBands(fitted).arrayFlatten([['year', 'fitted_value']]); // 提取目标点的数值 var pointData = yearFitted.sampleRegions({ collection: ee.FeatureCollection(points), scale: 30, geometries: true }); // 打印结构化数据到控制台 print('年份-拟合值表格数据', pointData); // 导出到Google Drive为CSV表格 Export.table.toDrive({ collection: pointData, description: 'LandTrendr_Fitted_Values', folder: 'GEE_Results', fileFormat: 'CSV' });
内容的提问来源于stack exchange,提问作者babak asadolah
相关产品推荐
相关产品推荐

