遥感入门不求人:用Python+ENVI 5.3快速识别植被、水体与裸土(附光谱曲线对比图)
遥感地物分类实战:Python+ENVI 5.3光谱特征解析与自动化识别
第一次接触遥感影像分类时,面对屏幕上五彩斑斓的像素矩阵,我完全无法理解如何区分植被、水体和裸土。直到一位前辈指着近红外波段的灰度图说:"看,这些深色区域就是水体,它们像黑洞一样吞噬了近红外光。"这个直观比喻让我瞬间开窍——原来地物分类的钥匙就藏在光谱反射率的微妙差异中。
本文将带您用ENVI 5.3和Python重现这个认知突破的过程。我们不会停留在理论层面,而是直接处理真实的Landsat 8影像,通过三个典型场景演示:如何观察不同地物的光谱特征曲线,如何基于这些特征制定分类规则,以及如何用代码批量实现自动化提取。特别准备了可复现的Python代码片段和常见错误排查指南,帮助您避开我当年踩过的坑。
1. 环境配置与数据准备
工欲善其事,必先利其器。我们需要配置一个既能处理遥感影像又能运行机器学习分类的环境。推荐使用Anaconda创建专属Python环境:
conda create -n remote_sensing python=3.8 conda activate remote_sensing conda install -c conda-forge rasterio scikit-learn matplotlibENVI 5.3的安装相对简单,但需要注意两个关键点:
- 安装时勾选"ENVI Classic"选项保留传统界面
- 确保安装路径不含中文或特殊字符
实验数据采用Landsat 8 Level-2表面反射率产品(LC08_L2SP_123032_20200520_20200529_02_T1),主要利用以下波段:
| 波段编号 | 光谱范围(μm) | 主要应用 |
|---|---|---|
| B2 | 0.45-0.51 | 蓝光波段 |
| B3 | 0.53-0.59 | 绿光波段 |
| B4 | 0.64-0.67 | 红光波段 |
| B5 | 0.85-0.88 | 近红外(NIR) |
| B6 | 1.57-1.65 | 短波红外1(SWIR1) |
提示:USGS官网提供免费的Landsat数据下载,建议选择云量低于10%的影像以获得最佳效果
2. 光谱特征解析:三大地物的指纹图谱
在ENVI Classic中打开影像后,通过Tools > Profiles > Z Profile提取典型地物的光谱曲线。建议选择纯净像元(同质区域中心点)进行分析,以下是三大地物的光谱特征速查表:
植被光谱特征
- 绿光波段(B3)反射峰:0.55μm附近的小高峰
- 红光波段(B4)吸收谷:叶绿素强烈吸收导致
- 近红外(B5)陡升:细胞结构散射形成"红边"现象
- 短波红外(B6)骤降:叶片水分吸收带
水体光谱特征
- 整体反射率低(尤其近红外)
- 清洁水体在蓝绿波段(B2-B3)反射略高
- 近红外(B5)后反射几乎为零
- 含泥沙水体在黄红波段(B3-B4)反射增强
裸土光谱特征
- 反射曲线相对平缓
- 无显著吸收/反射峰
- 含水量影响整体反射强度
- 有机质含量越高反射越低
下图展示了三者在Landsat 8各波段的典型反射率值对比(模拟数据):
| 波段 | 植被反射率(%) | 水体反射率(%) | 裸土反射率(%) |
|---|---|---|---|
| B2 | 8.2 | 12.5 | 22.1 |
| B3 | 11.7 | 14.3 | 25.8 |
| B4 | 6.5 | 9.2 | 30.4 |
| B5 | 42.8 | 2.1 | 35.7 |
| B6 | 15.3 | 1.8 | 28.9 |
3. 规则分类法:基于阈值的快速提取
对于初学者,最简单的地物提取方法是设定光谱阈值。在ENVI中可以通过Basic Tools > Band Math输入逻辑表达式实现:
; 植被提取NDVI阈值法 (b5 - b4)/(b5 + b4) > 0.3 ; 水体提取NIR单波段阈值 b5 < 0.1 ; 裸土提取SWIR1/Red比值 (b6 / b4) > 0.8 and (b5 - b4)/(b5 + b4) < 0.2Python实现同样简单,使用rasterio读取影像后,通过numpy进行矩阵运算:
import rasterio import numpy as np with rasterio.open('landsat.tif') as src: b4 = src.read(4).astype(float) b5 = src.read(5).astype(float) ndvi = (b5 - b4) / (b5 + b4 + 1e-10) vegetation_mask = (ndvi > 0.3).astype(np.uint8)注意:阈值需要根据具体影像调整,建议先用ENVI的ROI工具统计典型地物的值域范围
常见错误处理:
- 波段顺序错乱:Landsat波段编号与数组索引可能不对应,建议先打印波段描述
- 除零错误:NDVI计算时分母需添加极小值(1e-10)防止崩溃
- 数据类型问题:uint8类型进行减法会产生溢出,需先转换为float
4. 机器学习方法:随机森林分类实战
当场景复杂(如混合像元)时,阈值法效果有限。这时可以训练一个简单的随机森林分类器。首先在ENVI中创建训练样本:
- 通过
ROI Tool绘制多边形选择典型区域 - 为每类地物采集至少50个样本点
- 导出样本数据为CSV格式
Python训练代码示例:
from sklearn.ensemble import RandomForestClassifier import pandas as pd # 加载训练数据 train_data = pd.read_csv('samples.csv') X = train_data[['B2','B3','B4','B5','B6']].values y = train_data['class'].values # 训练模型 clf = RandomForestClassifier(n_estimators=100, random_state=42) clf.fit(X, y) # 全图预测 with rasterio.open('landsat.tif') as src: data = src.read().transpose(1,2,0) rows, cols, bands = data.shape reshaped = data.reshape(rows*cols, bands) # 预测并 reshape回原尺寸 pred = clf.predict(reshaped).reshape(rows, cols)模型优化技巧:
- 添加NDVI、NDWI等指数作为特征
- 对样本进行标准化处理
- 使用交叉验证评估精度
- 尝试不同波段组合
5. 结果可视化与精度验证
分类结果需要直观展示和定量评估。ENVI中可通过Classic > Classification > Post Classification > Confusion Matrix计算精度指标,Python则可用sklearn的classification_report:
from sklearn.metrics import classification_report print(classification_report(y_true, y_pred, target_names=['水体','植被','裸土']))典型输出示例:
| 类别 | 准确率 | 召回率 | F1分数 |
|---|---|---|---|
| 水体 | 0.92 | 0.88 | 0.90 |
| 植被 | 0.85 | 0.91 | 0.88 |
| 裸土 | 0.78 | 0.75 | 0.76 |
可视化时建议使用ENVI的Layer Stacking将分类结果与原始影像叠加显示,Python用户可以用matplotlib制作专题图:
import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap cmap = ListedColormap(['blue','green','brown']) plt.imshow(pred, cmap=cmap, vmin=1, vmax=3) plt.colorbar(ticks=[1,2,3], label='类别') plt.title('地物分类结果') plt.show()在最近的一个湿地监测项目中,我发现当水体含有大量藻类时,单纯依靠NIR波段会漏检。这时需要结合NDVI和NDWI指数((B3-B5)/(B3+B5))进行综合判断。这种实际场景中的边界情况,正是遥感分类既充满挑战又引人入胜的地方。
