1. 遥感影像分类基础入门
第一次接触遥感影像分类时,我盯着屏幕上五彩斑斓的卫星图完全无从下手。后来才明白,这就像教计算机玩"找不同"游戏——只不过我们要找的是地表上的农田、森林、水域等地物类型。极大似然监督分类就是其中最经典的"游戏规则"之一。
传统分类方法主要分两大类:监督和非监督分类。监督分类就像老师手把手教学,需要我们先圈出样本区域(比如这片红色是城市,那片绿色是森林),计算机通过这些样本学习判别规则。而非监督分类则是让计算机自己找规律,适合我们对地物类型不太了解的场景。
为什么选择极大似然法?实测下来它的分类精度通常比最小距离、马氏距离等方法更稳定。原理其实很直观:假设每类地物的光谱特征都服从正态分布,当一个像元的光谱值在"森林"类中出现的概率最大时,就把它划为森林。就好比看到一只动物有羽毛和喙,我们判断它是鸟而不是鱼,因为鸟的特征组合出现概率更高。
在ENVI等商业软件中,这个算法已经被封装成工具按钮。但就像只会用计算器做算术无法成为数学家一样,要真正掌握分类精髓,就得从底层实现它。接下来我将用IDL语言,带大家从零搭建这个经典算法。
2. 数据准备与预处理
先准备好我们的"实验材料"——Landsat TM影像数据。这里我用的是LT51240362007139_JZ.img这个文件,包含6个波段的多光谱数据。在IDL中读取数据的代码如下:
ENVI_OPEN_FILE, tm_file, r_fid=fid ENVI_FILE_QUERY, fid, dims=dims, ns=ns, nl=nl, nb=nb tm_data = intarr(ns,nl,nb) tm_data[*,*,0] = envi_get_data(fid=fid, dims=dims, pos=0) ;...依次读取其他波段读取后建议做个简单检查:用print,tm_data[3,3,*]查看某个像元各波段值是否正常。遇到过数据异常的情况,比如全是0或65535(溢出值),这种像元需要后续过滤处理。
关键的一步是获取训练样本统计值。我们需要为每类地物准备两个核心参数:
- 均值向量:各类样本在各波段的平均值
- 协方差矩阵:反映各波段间的相关性
比如农田类的参数可能是:
mi_crop = [87.8,41.9,44.2,81.8,75.2,33.9] ;6个波段的均值 cov_crop = [[3.84,1.41,...], [...], ...] ;6×6协方差矩阵获取这些参数有两种途径:
- 在ENVI中圈选样本区域自动计算
- 手动测量典型地物样本(适合小区域验证)
建议新手先用方法1,记得检查样本可分离性——用ENVI的ROI Separability工具,Jeffries-Matusita指数大于1.9才合格。曾经因为样本区分度不够,导致分类结果一片混乱,这个坑大家一定要避开。
3. 极大似然算法核心实现
算法核心在于计算每个像元属于各类别的概率。公式看起来复杂,但拆解后很容易理解:
P(Class_i|x) = -\frac{1}{2}[\ln|\Sigma_i| + (x-\mu_i)^T\Sigma_i^{-1}(x-\mu_i)]用IDL实现这个公式时,重点注意三个操作:
- 矩阵求逆:
INVERT(cov_matrix) - 矩阵乘法:
#运算符 - 行列式计算:
DETERM()
具体实现如下:
For i=0,ns-1 do begin For j=0,nl-1 do begin x = Transpose(tm_data[i,j,*]) ;当前像元光谱向量 ;计算属于城市类的概率 diff = x - mi_city p_city = -(alog(determ(cov_city)) + $ transpose(diff)#invert(cov_city)#diff)/2 ;...同理计算其他类别概率 ;找出最大概率对应的类别 pro_array = [p_city, p_forest, p_water, p_crop, p_nudation] max_p = max(pro_array) ;给像元赋类别值 case 1 of (p_city eq max_p): class_data[i,j,*] = [255,0,0] ;红色 (p_forest eq max_p): class_data[i,j,*] = [33,138,33] ;绿色 ;...其他类别 endcase endfor endfor调试时遇到过两个典型问题:
- 协方差矩阵奇异导致求逆失败——解决方法是在对角线加微小扰动(如1e-6)
- 概率计算溢出——对数值太大时改用对数运算
4. 分类结果输出与优化
得到分类结果后,可以用ENVI的导出功能保存为图像:
envi_enter_data, class_data, map_info=map_info, r_fid=out_fid envi_output_to_external_format, fid=out_fid, out_name='result.img'但直接分类的结果往往会有"椒盐噪声"——零星散落的错分像元。这时需要后处理:
- 众数滤波:用3×3窗口内的多数类别替换中心像元
- 去除小图斑:删除面积小于阈值的孤立区域
IDL中实现众数滤波的代码片段:
kernel = [1,1,1,1,1,1,1,1,1] ;3×3矩形核 filtered = CONVOL(class_data, kernel, /NAN) class_data = (filtered ge 5) ? 1 : 0 ;阈值设为5我曾用北京郊区影像测试,未滤波的总体精度只有78%,滤波后提升到85%。但要注意滤波过度会导致地块边界模糊,需要在保持边界和去除噪声间权衡。
5. 精度验证与误区规避
分类结果不能只看视觉效果,必须定量评估。常用方法是混淆矩阵:
| 类别 | 实测农田 | 实测城市 | 实测水域 | 用户精度 |
|---|---|---|---|---|
| 分类农田 | 85 | 5 | 2 | 92.4% |
| 分类城市 | 3 | 72 | 1 | 94.7% |
| 分类水域 | 4 | 2 | 90 | 93.8% |
| 制图精度 | 92.4% | 91.1% | 96.8% | 总体精度=89.3% |
实现代码:
;假设有验证样本truth和分类结果result confusion = INTARR(nclass,nclass) FOR i=0, nclass-1 DO BEGIN FOR j=0, nclass-1 DO BEGIN confusion[i,j] = TOTAL((truth EQ i) AND (result EQ j)) ENDFOR ENDFOR新手容易踩的坑:
- 样本偏差:训练样本仅来自影像某区域,导致其他区域分类差
- 过拟合:样本太少时协方差矩阵估计不准
- 未考虑时相变化:夏季植被茂盛时训练的模型不适合冬季影像
有个项目曾因训练样本全来自旱季,导致雨季影像中水体被错分为阴影。后来通过增加多时相样本解决了这个问题。
6. 进阶优化方向
当基础版本跑通后,可以尝试以下优化:
- 波段选择:用J-M距离评估各波段区分度,剔除冗余波段
jm = 2*(1-exp(-bhattacharyya_distance))- 引入纹理特征:结合GLCM矩阵的对比度、同质性等指标
- 并行加速:将影像分块,用
MPI_LAUNCH并行计算
测试发现,加入NDVI指数作为额外波段,能使农田/草地区分精度提升7%。但要注意各特征量纲不同,需要标准化处理。
对于高光谱数据,建议先做MNF变换降维。曾经处理过200波段的AVIRIS数据,直接分类需要3小时,降维到30个主成分后只需15分钟,精度反而提高了2%。
7. 与其他算法的对比实验
在相同数据上对比几种算法效果:
| 算法 | 总体精度 | Kappa系数 | 运行时间 |
|---|---|---|---|
| 最大似然 | 89.3% | 0.86 | 2.1s |
| 支持向量机 | 91.2% | 0.89 | 15.7s |
| 随机森林 | 90.8% | 0.88 | 8.3s |
| 1D-CNN | 92.1% | 0.90 | 23.5s |
虽然深度学习更精准,但极大似然的优势在于:
- 物理意义明确
- 无需大量训练样本
- 计算效率高
特别是在应急监测场景下,当需要快速获取初步分类结果时,这个经典算法依然是首选。去年参与某次洪灾评估时,用极大似然法10分钟就完成了受灾范围估算,为救援决策争取了宝贵时间。