这里说一个导出数据可能会遇到的问题,当然这个问题不仅仅可能会出现在数据导出,在其他涉及到网络通信的操作都有可能会出现这个问题。
1、分析错误
首先先看一下报错的内容,如下图
分析一下报错的内容:“消息请求 payload 的大小超过了大小限制:4194304比特(1024 * 1024 = 1M)”
需要注意一下我标注的粗体内容
- 消息请求
- payload
- 大小限制
分析到这里,我们可以大致推断这个错误的问题出在和GEE服务器某个消息通信出问题了,下面用具体的例子来分析一下这个问题以及解决方法。
2、具体例子:
var Basin = ee.FeatureCollection("USGS/WBD/2017/HUC02"),
L5 = ee.ImageCollection("LANDSAT/LT05/C01/T1_SR");
var roi = Basin.filterMetadata('name','equals','Tennessee Region');
Map.addLayer(roi, {}, "roi");
function cloudmask (img) {
var qa = img.select(['pixel_qa']);
var mask = qa.bitwiseAnd(8).eq(0).and( // Clouds
qa.bitwiseAnd(16).eq(0)).and( // Shadows
qa.bitwiseAnd(32).eq(0)); // Clouds
return img.updateMask(mask).clip(roi);
}
var start = ee.Date('1994-01-01');
var stop = ee.Date('1995-01-01');
var band1 = ['B6', 'B5', 'B4','B3', 'B1'];
var band2 = ['swir1', 'nir','red', 'green','blue'];
var l5 = L5.filterDate(start, stop)
.filterBounds(roi)
.map(cloudmask)
.select(band1, band2);
var image = l5.median().clip(roi);
Map.addLayer(image, {min:0, max:3000, gamma:0.7, bands:["swir1","red", "green"]}, "Image");
Export.image.toAsset({
image: image.select('nir'),
description: "TestExportL5Image",
assetId: "TestExportL5Image",
scale: 30,
region: roi,
maxPixels: 1e13,
crs: "EPSG:4326"
});
运行后点击导出数据
根据我们之前的分析,下一步我们需要查看消息通信中报错的问题,经过查找是下面这条消息报错了
携带的请求参数payload
返回的结果是400,内容如下
如果更进一步查询参数内容可以发现,这里有一个参数不正常,调用clipToBoundsAndScale后,它的Polygon点有快9万个了。问题就出在这里,由于这个数据非常大造成request请求根本就发不出去,所以我们要找的为什么这个polygon这么大。
我们重新查看一下代码,这个方法调用对应的其实是Export.image.toAsset()中参数 region,那么问题的原因是roi造成的。要解决这个问题也不难,理解了问题的原因那么只要我们使用的边界region小一些没有这么复杂就可以了,因此通常我们使用roi.geometry().bounds()来做。
3、解决方案:
var Basin = ee.FeatureCollection("USGS/WBD/2017/HUC02"),
L5 = ee.ImageCollection("LANDSAT/LT05/C01/T1_SR");
var roi = Basin.filterMetadata('name','equals','Tennessee Region');
Map.addLayer(roi, {}, "roi");
function cloudmask (img) {
var qa = img.select(['pixel_qa']);
var mask = qa.bitwiseAnd(8).eq(0).and( // Clouds
qa.bitwiseAnd(16).eq(0)).and( // Shadows
qa.bitwiseAnd(32).eq(0)); // Clouds
return img.updateMask(mask).clip(roi);
}
var start = ee.Date('1994-01-01');
var stop = ee.Date('1995-01-01');
var band1 = ['B6', 'B5', 'B4','B3', 'B1'];
var band2 = ['swir1', 'nir','red', 'green','blue'];
var l5 = L5.filterDate(start, stop)
.filterBounds(roi)
.map(cloudmask)
.select(band1, band2);
var image = l5.median().clip(roi);
Map.addLayer(image, {min:0, max:3000, gamma:0.7, bands:["swir1","red", "green"]}, "Image");
// print("roi",roi);
// Export.image.toAsset({
// image: image.select('nir'),
// description: "TestExportL5Image",
// assetId: "TestExportL5Image",
// scale: 30,
// region: roi,
// maxPixels: 1e13,
// crs: "EPSG:4326"
// });
Export.image.toAsset({
image: image.select('nir'),
description: "TestExportL5Image",
assetId: "TestExportL5Image",
scale: 30,
region: roi.geometry().bounds(),
maxPixels: 1e13,
crs: "EPSG:4326"
});
4、总结思考
我们简单思考一下为什么会有这个问题?具体是什么造成我们在做这些操作的时候需要将整体的数据全部传给GEE服务器后台?从我个人理解出现这个问题的原因是,由于GEE安全权限设置,有些操作不能直接访问一些私有的内容,为了解决这些问题只能把所有的数据都当作是已知量传递给后台,这样后台才能做相关操作。问题是这样无形中增加了消息的传输量,为了解决这种问题,我们只能在某些参数上尽量减少参数大小。