You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用geetools绘制Landsat NDVI与EVI时序图空白问题排查

Landsat 8 NDVI/EVI时序图表空白排查(MODIS正常)

我用Google Earth Engine生成Landsat 8的NDVI与EVI时序图表,切换到Landsat 8影像集后图表空白,但MODIS影像集运行正常。已经确认Landsat计算出的NDVI、EVI值存在且合理,求排查问题。

#--------------------------------------------------------------------------------------
#Python Script to Explore Google Earth Engine
#--------------------------------------------------------------------------------------
import ee
import geetools
import pandas as pd
import geopandas as gpd
import sys 
import os 
import matplotlib.pyplot as plt
from datetime import datetime as d
#--------------------------------------------------------------------------------------
#Functions
#--------------------------------------------------------------------------------------
def apply_scale_factors_ls(image):
    #--These are scale factors for landsat
    try:
      optical_bands = image.select('SR_B.*').multiply(0.0000275).add(-0.2)
      image = image.addBands(optical_bands, None, True)
    except:
      pass 
    return image

def apply_scale_factors_modis(image):
    #--These are scale factors for landsat
    try:
      ndvi = image.select('NDVI').multiply(0.0001)
      evi = image.select('EVI').multiply(0.0001)
      image = image.addBands(ndvi, None, True)
      image = image.addBands(evi, None, True)
    except:
      pass 
    return image
  
def calculate_ndvi(img):
    ndvi = img.normalizedDifference(['SR_B5', 'SR_B4']).rename('NDVI')
    #img.addBands(ndvi)
    #img.select().addBands(ndvi)
    return img.addBands(ndvi)

def calculate_evi(img):
    evi_img = img.select(['SR_B5', 'SR_B4', 'SR_B2'], ['nir', 'red', 'blue'])
    evi_img = evi_img.expression(
        '(2.5 * (NIR - RED)) / (NIR + 6 * RED - 7.5 * BLUE + 1)',
        {
            'NIR': evi_img.select('nir'),
            'RED': evi_img.select('red'),
            'BLUE': evi_img.select('blue')
        }
    ).rename('EVI')
    return img.addBands(evi_img)
#----------------------------------------------------------------------------------
#--Current Working code
#----------------------------------------------------------------------------------
ee.Authenticate()
ee.Initialize(project='bold-camera-445217-d4')
#----------------------------------------------
#--Get our imagery collection 
date_start =  "2018-01-01"
date_end =    "2024-12-01"

bc_extent = ee.Geometry.Rectangle([-139.2,47.5,-113.84,60.1]) 
#bc = geojson_eefc(bc_bounds)
#--MODIS Collection 
sensor = 'MODIS/061/MOD13Q1'
ic = (
    #ee.ImageCollection('MODIS/061/MOD13A1') 
    ee.ImageCollection(sensor) 
    .filter(ee.Filter.date(date_start, date_end)) 
    .select(['NDVI', 'EVI'])
    .map(apply_scale_factors_modis)
    .filterBounds(bc_extent)
    )
maxPixels = 10000000
scale = 500    
#---Landsat Collection 
sensor = 'LANDSAT/LC08/C02/T1_L2'
ic = (
    ee.ImageCollection(sensor)
    .filterDate(date_start, date_end)
    .select(['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B5']) 
    .map(apply_scale_factors_ls)
    .map(calculate_ndvi)
    .map(calculate_evi)
    .filterMetadata('CLOUD_COVER', 'less_than', 10)
    .filterBounds(bc_extent)
    )
maxPixels = 300000000
scale = 30
#----------------------------------------------
aoi = ee.Geometry.Polygon([[-124.1753755674451, 51.358079942703306], [-124.0019949017465, 51.358079942703306], [-124.0019949017465, 51.45478364277703], [-124.1753755674451, 51.45478364277703], [-124.1753755674451, 51.358079942703306]])

fig, ax = plt.subplots(figsize=(10, 4))
#--Plot the Current AOS Feature   
ic.geetools.plot_dates_by_bands(
  region = aoi,
  reducer = "mean",
  scale = scale, 
  bands = ["NDVI", "EVI"],
  colors = ["#0193c2","#028352"],
  ax = ax,
  dateProperty = "system:time_start",
  maxPixels = maxPixels
)
ax.set_ylabel("Vegetation Index")
ax.set_title(f"Average Vegetation Index Values in AOS Feature \n {sensor}")

plt.show()

对比截图

  • MODIS NDVI图表正常显示:MODIS NDVI正常图表
  • Landsat 8 NDVI图表空白:Landsat 8 NDVI空白图表

问题排查与修复方案

核心问题是Landsat影像集的过滤顺序错误,导致无效影像(不在AOI内或云量过高)被提前处理,同时缺少时序排序,影响geetools的图表渲染逻辑。

修复后的Landsat影像集代码段

#---Landsat Collection 
sensor = 'LANDSAT/LC08/C02/T1_L2'
ic = (
    ee.ImageCollection(sensor)
    .filterDate(date_start, date_end)
    .filterBounds(bc_extent)  # 先过滤AOI范围,减少无效计算
    .filterMetadata('CLOUD_COVER', 'less_than', 10)  # 先过滤云量,保留有效影像
    .select(['SR_B1', 'SR_B2', 'SR_B3', 'SR_B4', 'SR_B5']) 
    .map(apply_scale_factors_ls)
    .map(calculate_ndvi)
    .map(calculate_evi)
    .sort('system:time_start')  # 按时间排序,确保时序逻辑正确
)
maxPixels = 300000000
scale = 30

备选手动绘图方案(规避geetools潜在兼容问题)

如果上述调整后仍有问题,可以手动提取时序数据到Pandas再绘图,更可控:

# 提取AOI内的均值时间序列
def extract_ts(image):
    mean_val = image.reduceRegion(
        reducer=ee.Reducer.mean(),
        geometry=aoi,
        scale=scale,
        maxPixels=maxPixels
    )
    return ee.Feature(None, {
        'NDVI': mean_val.get('NDVI'),
        'EVI': mean_val.get('EVI'),
        'date': ee.Date(image.get('system:time_start')).format('YYYY-MM-dd')
    })

# 获取特征集并转为Pandas DataFrame
ts_features = ic.map(extract_ts).getInfo()['features']
ts_data = pd.DataFrame([feat['properties'] for feat in ts_features])
ts_data['date'] = pd.to_datetime(ts_data['date'])

# 绘制图表
fig, ax = plt.subplots(figsize=(10, 4))
ts_data.plot(x='date', y='NDVI', color='#0193c2', ax=ax, label='NDVI')
ts_data.plot(x='date', y='EVI', color='#028352', ax=ax, label='EVI')
ax.set_ylabel("植被指数")
ax.set_title(f"AOI内平均植被指数时序图 \n {sensor}")
ax.legend()
plt.show()

内容的提问来源于stack exchange,提问作者fowlermw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:47:01