GEE学习笔记 四十六:使用GEE常见错误及解决方案(二)

日期:

继续来说一下GEE中一些常见错误以及解决方案。


  • GEE中计算时候错误使用四则运算

先看一个具体的例子

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Col = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-5-1") 
              .filterBounds(geometry) 
              .map(function(image) { 
                return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI")); 
              }) 
              .select("NDVI"); 
var img = l8Col.mosaic(); 
print("img", img); 
Map.addLayer(img, {min:0, max:0.8, palette:"ff0000,00ff00,0000ff"}, "NDVI"); 
//错误:直接将影像加1 
var img1 = img + 1; 
print("img1", img1);

先看一下输出结果:

 

分析:直接运行这段代码并没有任何错误,但是输出结果可以看到第一个img是正常影像,第二个img1却是一个json的字符串(其实这里是img1的数据描述)。有的小伙伴在写程序的时候,如果一不小心将其写为这样,在使用这个影像的时候就会出现错误。


我们测试使用一下这个资源:

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Col = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-5-1") 
              .filterBounds(geometry) 
              .map(function(image) { 
                return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI")); 
              }) 
              .select("NDVI"); 
var img = l8Col.mosaic(); 
print("img", img); 
Map.addLayer(img, {min:0, max:0.8, palette:"ff0000,00ff00,0000ff"}, "NDVI"); 
//error 
var img1 = img + 1; 
// print("img1", img1); 
Map.addLayer(img1, {min:1, max:1.8, palette:"ff0000,00ff00,0000ff"}, "NDVI1"); 

输出结果:

分析:这里很明确指出了添加的image不是一个影像,而是一堆Json数据。

正确的写法,使用GEE内部封装好的方法:add() subtract() multiply() divide() 等等。

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Col = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-5-1") 
              .filterBounds(geometry) 
              .map(function(image) { 
                return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI")); 
              }) 
              .select("NDVI"); 
var img = l8Col.mosaic(); 
print("img", img); 
Map.addLayer(img, {min:0, max:0.8, palette:"ff0000,00ff00,0000ff"}, "NDVI"); 
//error 
// var img1 = img + 1; 
// print("img1", img1); 
// Map.addLayer(img1, {min:1, max:1.8, palette:"ff0000,00ff00,0000ff"}, "NDVI1"); 


//correct 
var img1 = img.add(1); 
print("img1", img1); 
Map.addLayer(img1, {min:1, max:1.8, palette:"ff0000,00ff00,0000ff"}, "NDVI1"); 

我们点击一点验证一下是否计算成功,从结果可以看到数据已经更新成功。

总结:在GEE中的各种计算,我们一定要记住使用GEE已经封装好的方法,而不是我们通常编程使用的“+-*/”之类。
  • 影像添加属性失败

这个非常普遍,尤其是接触GEE时间不是很久的用户,经常会出现想要添加属性,最终却发现属性丢失的状况。先看如下一段代码

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Img = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-10-1") 
              .filterBounds(geometry) 
              .first(); 
print("img1", l8Img); 
var time_start = l8Img.get("system:time_start"); 
var year = ee.Date(time_start).get("year"); 


//错误方法,虽然设置了属性 year ,但是为将设置后的影像重新赋值给 l8Img 
l8Img.set("year", year); 
print("img2", l8Img); 


//正确方法 
l8Img = l8Img.set("year", year); 
print("img3", l8Img); 

先看一下输出结果:

分析:从结果输出可以看到img2没有将属性“year”添加到影像中,而img3添加成功。这里我们需要注意的是在GEE中的方法大部分都是有返回值的,它是将数据进行计算后然后将计算结果返回,而不是修改原有的数据,所以我们在使用的时候一定要记得将数据重新赋值。
  • 影像属性丢失,找不到相关属性

这个问题比较隐蔽,如果不注意很容易出现,先看一段代码

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Col = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-5-1") 
              .filterBounds(geometry) 
              .map(function(image) { 
                return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI")); 
              }) 
              .select("NDVI"); 
var img = l8Col.first(); 
var index = img.get("system:index"); 
var time_start = img.get("system:time_start"); 
print("img", img); 
print("img system:index", img.get("system:index")); 
print("img system:time_start", img.get("system:time_start")); 
//这里有个隐藏的问题 
var img1 = img.add(1); 
print("img1", img1); 
print("img1 system:index", img1.get("system:index")); 
print("img1 system:time_start", img1.get("system:time_start")); 

运算结果:

分析:影像进行四则运算,不光是波段会发生变化,同样的属性也会随之发生变化。尤其是一张影像和一个常量进行四则运算后,结果的属性是丢失了的,这个是GEE的运算规则决定的。因此我们在实际开发中遇到这种情况如果需要保留某些属性,一定要记着重新赋值。

相关代码如下

var geometry = ee.Geometry.Point([-104.78007812499999, 37.07682857623016]); 
var l8Col = ee.ImageCollection("LANDSAT/LC08/C01/T1_RT_TOA") 
              .filterDate("2018-2-1", "2018-5-1") 
              .filterBounds(geometry) 
              .map(function(image) { 
                return image.addBands(image.normalizedDifference(["B5", "B4"]).rename("NDVI")); 
              }) 
              .select("NDVI"); 
var img = l8Col.first(); 
var index = img.get("system:index"); 
var time_start = img.get("system:time_start"); 
print("img", img); 
print("img system:index", img.get("system:index")); 
print("img system:time_start", img.get("system:time_start")); 


// var img1 = img.add(1); 
// print("img1", img1); 
// print("img1 system:index", img1.get("system:index")); 
// print("img1 system:time_start", img1.get("system:time_start")); 


// 将原有的属性复制过来 
var img2 = img.add(1); 
img2 = img2.set("system:index", index); 
img2 = img2.set("system:time_start", time_start); 
print("img2", img2); 
print("img2 system:index", img2.get("system:index")); 
print("img2 system:time_start", img2.get("system:time_start")); 

显示结果:

下一篇会讲解一下map相关错误。