Landsat计算NDVI公式?植被指数怎么算?

GIS基础理论
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

Landsat计算NDVI公式?植被指数怎么算? 这是很多 GIS 初学者、遥感制图人员在处理 Landsat 影像时最常遇到的问题。NDVI 看起来只是一个简单公式,但如果波段选错、反射率没有处理好、云和无效值没有掩膜,计算结果很容易出现整幅图偏黑、数值超出 -1 到 1、植被区反而不高等问题。

本文以 Landsat 8/9 和 Landsat 5/7 为主,讲清楚 Landsat 计算 NDVI 公式、不同传感器对应波段、在 QGIS 和 Python 中的计算方法,以及如何检查结果是否可靠。

引言:Landsat计算NDVI公式的核心答案

NDVI 的全称是归一化植被指数,英文为 Normalized Difference Vegetation Index。它利用植被在近红外波段反射强、在红光波段吸收强的特点,来判断地表植被覆盖状况。

Landsat 计算 NDVI 的通用公式是:

NDVI = (NIR - Red) / (NIR + Red)

其中:

  • NIR:近红外波段。
  • Red:红光波段。
  • NDVI:理论范围通常在 -1 到 1 之间。

对于常见 Landsat 数据,波段对应关系如下:

数据类型 红光 Red 近红外 NIR NDVI 公式
Landsat 8 / Landsat 9 OLI Band 4 Band 5 (B5 – B4) / (B5 + B4)
Landsat 5 TM Band 3 Band 4 (B4 – B3) / (B4 + B3)
Landsat 7 ETM+ Band 3 Band 4 (B4 – B3) / (B4 + B3)
Landsat计算NDVI公式与Landsat 8 NDVI计算波段示意图
Landsat 8/9 计算 NDVI 的基本流程:选择红光和近红外波段,再按公式生成植被指数栅格。

背景:为什么植被指数不能直接用任意两个波段算

很多人第一次计算植被指数时,会把影像中的两个波段直接套进公式。这样做经常出错,因为 NDVI 依赖的是明确的光谱物理意义:红光波段和近红外波段。

健康植被的叶绿素会强烈吸收红光,用于光合作用;同时叶片内部结构会强烈反射近红外。因此健康植被通常表现为 NIR 值明显大于 Red 值,NDVI 接近正值,并且植被越旺盛,NDVI 越高。

如果把蓝光、绿光、短波红外或热红外误当成红光和近红外,计算出来的结果虽然也可能在数值上有变化,但已经不再是标准 NDVI,无法正确表示植被覆盖。

原理:NDVI数值应该如何理解

NDVI 的结果通常位于 -1 到 1 之间。实际解释时不要只看颜色,还要查看像元值范围和空间分布。

NDVI 范围 常见地物含义 说明
小于 0 水体、云、阴影、雪等 近红外反射通常较低,可能出现负值。
0 到 0.2 裸地、建设用地、稀疏植被 植被信号弱,需结合影像和土地类型判断。
0.2 到 0.5 草地、农田、稀疏林地 一般表示中等植被覆盖。
0.5 以上 茂密植被、森林、长势良好的农作物 通常表示植被活性较强。

需要注意,NDVI 不是“植被面积”的直接结果,而是每个像元的植被指数。如果要统计植被面积,还需要设置阈值并计算满足条件的像元面积。

步骤:在QGIS中计算Landsat NDVI

步骤一:确认 Landsat 数据类型

先查看影像文件名或元数据,确认是 Landsat 8/9、Landsat 5,还是 Landsat 7。不同 Landsat 传感器的波段编号不同,这是 Landsat NDVI 计算中最容易出错的地方。

  • Landsat 8/9:红光 Band 4,近红外 Band 5。
  • Landsat 5/7:红光 Band 3,近红外 Band 4。
  • 如果使用的是 Collection 2 Level-2 数据,优先使用地表反射率产品。

步骤二:加载红光和近红外波段

在 QGIS 中打开“图层”菜单,添加对应的 Landsat 波段栅格。建议先分别加载 Red 和 NIR 波段,检查范围、分辨率和坐标系是否一致。

如果两幅影像范围不同、像元大小不同或没有对齐,计算结果可能出现边缘错位或大量空值。一般同一景 Landsat 的标准产品已经对齐,但裁剪、重采样或格式转换后仍然需要检查。

步骤三:打开栅格计算器

在 QGIS 中选择:

栅格 → 栅格计算器

如果是 Landsat 8/9,表达式可以写成:

("B5@1" - "B4@1") / ("B5@1" + "B4@1")

如果是 Landsat 5/7,表达式可以写成:

("B4@1" - "B3@1") / ("B4@1" + "B3@1")

这里的图层名称需要替换成你在 QGIS 图层面板中看到的实际名称。不同文件名导入后,可能不是简单的 B4、B5。

步骤四:设置输出数据类型

NDVI 是小数结果,因此输出栅格应使用浮点型。不要把结果保存为整型,否则小数会被截断,导致结果只有 -1、0、1 或大量 0。

建议输出为 GeoTIFF 格式,例如:

landsat_ndvi.tif

步骤五:设置符号系统并检查数值

计算完成后,在图层属性中设置单波段伪彩色渲染。常见的颜色方案是低值为棕色或灰色,高值为绿色。

同时使用“识别要素”工具点击水体、裸地、农田、林地等区域,检查 NDVI 数值是否符合常识:

  • 水体通常为负值或接近 0。
  • 城市建设区和裸地通常较低。
  • 农田、草地、林地通常为正值。
  • 茂密森林或长势良好的作物通常较高。

步骤:用Python计算Landsat NDVI

如果需要批量处理多景 Landsat 影像,可以使用 Python 的 rasterio 库计算 NDVI。下面示例适用于已经准备好的红光和近红外单波段 GeoTIFF。

import rasterio
import numpy as np

red_path = "LC09_B4.tif"
nir_path = "LC09_B5.tif"
out_path = "landsat_ndvi.tif"

with rasterio.open(red_path) as red_src:
    red = red_src.read(1).astype("float32")
    profile = red_src.profile

with rasterio.open(nir_path) as nir_src:
    nir = nir_src.read(1).astype("float32")

np.seterr(divide="ignore", invalid="ignore")

ndvi = (nir - red) / (nir + red)
ndvi[(nir + red) == 0] = np.nan

profile.update(
    dtype=rasterio.float32,
    count=1,
    nodata=np.nan
)

with rasterio.open(out_path, "w", **profile) as dst:
    dst.write(ndvi.astype("float32"), 1)

print("NDVI saved:", out_path)

这段代码的关键点有三个:

  • 把输入影像转换为 float32,避免整数运算导致小数结果异常。
  • 处理 NIR + Red 等于 0 的像元,避免除以 0。
  • 保留原始影像的空间参考和仿射变换信息,使输出 NDVI 可以直接叠加到 GIS 软件中。

常见坑:Landsat计算NDVI结果不对的原因

1. Landsat 8/9 和 Landsat 5/7 波段混用

这是最常见错误。Landsat 8/9 的 NDVI 是 Band 5 和 Band 4,而 Landsat 5/7 是 Band 4 和 Band 3。如果把 Landsat 8 的 Band 4 当作近红外,就会把红光放错位置,结果完全失真。

2. 没有使用反射率数据

NDVI 最推荐使用地表反射率或表观反射率数据。如果直接使用原始 DN 值,虽然在某些同景影像中也可能得到近似结果,但不同日期、不同传感器、不同太阳高度角之间的结果可比性会变差。

如果你使用 USGS Landsat Collection 2 Level-2 产品,应注意地表反射率波段通常需要按元数据中的比例因子和偏移量还原。不要在不了解数据含义的情况下把所有波段直接当作真实反射率。

3. 云、云影和雪没有掩膜

云、云影和雪会显著干扰 NDVI。特别是在农作物长势监测、植被变化分析中,如果不做质量掩膜,某些区域的 NDVI 下降可能只是云影造成的。

实际项目中应结合 QA 波段或云掩膜产品,先剔除云、云影、雪和无效像元,再进行统计分析。

4. 输出为整型导致小数丢失

NDVI 是小数指数。如果栅格计算器输出为 Byte、Int16 或其他整型格式,结果可能被截断。正确做法是输出为 Float32 或 Float64。

5. 分母接近 0 导致异常值

当 NIR + Red 非常小或等于 0 时,NDVI 会出现无穷值或异常值。计算时应设置 NoData 或掩膜条件,避免这些异常值影响后续统计。

方法比较:QGIS、ArcGIS Pro和Python怎么选

方法 适合场景 优点 注意事项
QGIS 栅格计算器 单景影像、教学练习、快速制图 免费、操作直观、适合初学者 要手动确认波段名称和输出类型。
ArcGIS Pro 栅格函数 企业环境、制图流程、影像分析项目 界面完整,可结合影像分析工具链 需注意许可和栅格函数参数设置。
Python rasterio 批量处理、多期 NDVI、自动化流程 可重复、可扩展、适合批处理 需要处理 NoData、投影、对齐和数据类型。
Google Earth Engine 大范围、多时相、云端遥感分析 无需本地下载大量数据,适合时序分析 需要掌握 GEE 脚本和数据集属性。

如果只是学习 Landsat 计算 NDVI 公式,建议先用 QGIS 做一景影像,理解波段和结果范围。等流程跑通后,再用 Python 或 Google Earth Engine 做批量计算。

检查清单:计算NDVI前后必须确认什么

  • 是否确认 Landsat 传感器类型:Landsat 8/9、Landsat 5 或 Landsat 7。
  • 是否选择了正确的红光和近红外波段。
  • 是否使用反射率数据,或至少清楚输入数据是 DN、TOA 反射率还是地表反射率。
  • Red 和 NIR 是否空间范围一致、像元大小一致、坐标系一致。
  • 是否处理云、云影、雪、水体或 NoData。
  • 输出 NDVI 是否为浮点型栅格。
  • 结果值是否大致落在 -1 到 1 之间。
  • 高 NDVI 区域是否与影像中的植被区域对应。
  • 是否记录了数据日期、传感器、公式和处理参数,方便复现。

FAQ:Landsat计算NDVI公式常见问题

Landsat 8 NDVI 计算到底用哪两个波段?

Landsat 8 NDVI 计算使用 Band 5 作为近红外 NIR,Band 4 作为红光 Red,公式为:

NDVI = (Band 5 - Band 4) / (Band 5 + Band 4)

Landsat 5 和 Landsat 7 的 NDVI 公式一样吗?

常用公式一样,都是用近红外减红光再除以两者之和。区别在于波段编号:Landsat 5 TM 和 Landsat 7 ETM+ 通常使用 Band 4 作为近红外,Band 3 作为红光。

植被指数怎么算才算正确?

首先要确认植被指数类型。NDVI 使用 NIR 和 Red;如果是 EVI、SAVI、NDWI 等指数,公式和波段会不同。对于 NDVI,正确做法是使用对应传感器的红光和近红外波段,并尽量使用经过辐射校正和大气校正的反射率数据。

NDVI结果为什么出现大于1或小于-1?

常见原因包括数据类型错误、比例因子未处理、分母接近 0、NoData 没有掩膜、波段不匹配或计算表达式写错。正常情况下,标准 NDVI 结果通常应位于 -1 到 1 之间。

可以直接用Landsat原始DN值计算NDVI吗?

学习公式时可以尝试,但正式分析不建议直接使用原始 DN 值。因为 DN 值受传感器定标、太阳高度角、大气条件等影响,不同日期之间不具备稳定可比性。项目分析应优先使用反射率产品。

NDVI越高就一定表示植被越好吗?

不一定。NDVI 较高通常表示植被覆盖和活性较强,但它会受到作物类型、季节、土壤背景、地形阴影、水分条件和云影影响。判断植被长势时,最好结合多期影像、地面样点或其他指数一起分析。

结论:先选对波段,再谈植被指数分析

Landsat计算NDVI公式并不复杂,核心就是 NDVI = (NIR – Red) / (NIR + Red)。真正容易出错的是 Landsat 波段选择、输入数据类型、云掩膜、NoData 和输出格式。

记住一个实用规则:Landsat 8/9 用 Band 5 和 Band 4,Landsat 5/7 用 Band 4 和 Band 3。先用 QGIS 跑通一景影像,确认 NDVI 数值和地物分布合理,再扩展到 Python 批处理或多期植被变化分析,结果会更可靠。