本文为了实现对喜马拉雅山地区的冰湖进行简单快速的提取,借鉴了一篇论文[1]中的方法,并对其加以扩充,实现了基于双峰阈值分割的冰湖提取方法和基于阈值迭代的冰湖提取方法。快速准确的获得冰湖的分布及变化信息,对高原地区水资源评价具有重要意义。
[1]李均力, 盛永伟, 骆剑承. 喜马拉雅山地区冰湖信息的遥感自动提取[J]. 遥感学报, 2011, 15(1): 29-43
PS:相应python版本的代码可参见:基于双峰阈值分割的冰湖提取算法(python语言实现)
对于冰湖来说,其多发育在高原区域,且面积一般较小,数量较多。不同冰湖的发育环境存在差异,因此较难利用单一水体指数实现全局的冰湖提取。若要对冰湖准确提取,可考虑论文中的“全局——局部”的提取算法。
在对局部冰湖进行提取的过程中,先利用归一化水体指数NDWI对图像进行处理,目的是为了突出冰湖信息,抑制背景信息。处理后“局部”地物的NDWI信息具有双峰分布的特点,其分布特征如下图所示:
若水体像元和背景像元均值分别为和,方差分别为和,则最佳阈值可以表示为:
最后,若像元的NDWI值大于最优阈值T,则像元被认为是水体,否则被认为是背景。为了更好的说明这个方法,论文中给出了一些冰湖提取的例子,例如对错郎玛冰湖的提取效果:
该方法与双峰分布的阈值分割法类似,但是由于双峰分布的阈值分割法容易向方差大的地物偏移,冰湖与背景的NDWI分布差异较大,冰湖的NDWI值过于集中,这就造成了该方法得到的最优阈值偏小。
因此实验又添加了传统的阈值分割方法,阈值分割的公式为:
实验的数据为Landsat 8 OLI数据,该数据可从USGS上获取,数据行列号为140/40。实验区域为聂拉木县东南区域和定日县西南区域的交接处,经度范围为:86°07′58″-86°34′07″,纬度范围为:28°03′44″-28°08′11″,该处具有代表性的冰川为错朗玛冰川,该冰川发育有多条冰湖,最大的湖泊名为错朗玛冰湖。
试验区域的遥感图为:
实验数据需要进行简单的预处理,包括:图像裁剪,像元DN(digital number)值转TOA(top of atmosphere)。转化之后的的结果应如下所示:
IDL语言的实验步骤为:
这一步比较简单,直接读取文件即可,读取之后简单计算NDWI,并显示图像,核心代码为:
;①读取文件并显示----------------------------------------------------------------------------
file = ENVI_PICKFILE(title='Pick a tiff file', filter='*.TIF')
IF ~FILE_TEST(file) THEN RETURN
;显示二值掩膜图像
im1 = IMAGE(file, $
MARGIN=0,title='bw image of water and background')
;计算NDWI
envi_open_file,filename,r_fid=fid
envi_select,fid=fid,dims=dims,pos=pos
band3=envi_get_data(fid=fid,dims=dims,pos=2)
band5=envi_get_data(fid=fid,dims=dims,pos=4)
NDWI=(band3-band5)/(band3+band5)
NDWI=reverse(NDWI,2)
;------------------------------------------------------------------------------------------
这一步的目的是进行粗略的水体提取,得到全局掩膜,该掩膜包括了所有水体和一部分的背景,比如融化的冰川,山体阴影。
实验表明,初始全局阈值分割时,NDWI取值在[-0.1,0.1]之间的时候,可以提取出所有水体,一般选在初始阈值为0.05。同时,可以辅以短波红外波段的数据来减少融化冰川的影响,本实验选取NIR<0.15,SWIR<0.05。最后为了减少噪音的影响,可以采用形态学开运算的方法,先对图像进行腐蚀,去除图像上的噪音,之后对图像进行膨胀,填充不完整的区域。
这一步粗略提取所有的冰湖,并为这些冰湖进行编号,核心代码为:
;②标记各个水体------------------------------------------------------------------------------
;将图像存储在一个矩阵里面
imagess=read_tiff(file)
;size函数获得图像矩阵信息
imagedims=size(imagess)
;正确显示图像
; window,/free,xsize=imagedims[1],ysize=imagedims[2]
imagess=reverse(imagess,2)
; tv,imagess
; wshow
;初始化
b=imagess
c=bytarr(imagedims[0],imagedims[1]) ;c设置为N×M的0值矩阵
;标记水体区域
c=b gt 0 ;将图像变为二值区域
d=label_region(c)
;统计像元数量大于5个的区域个数
h = HISTOGRAM(d,min=1,REVERSE_INDICES=r) ;0为图像背景
;------------------------------------------------------------------------------------------
实验以错郎玛冰湖为例,处理后的结果为:
建立缓冲区的目的是为了进行下一步的局部阈值分割。建立缓冲区的思路是先对湖泊进行编号,然后对每一个湖泊进行膨胀,直到膨胀后的面积略大于原始湖泊面积的2倍。这一步需要在IDL中进行编程实现,实现的结果如下:
在IDL中的核心代码如下:
以错郎玛冰湖为例,计算NDWI值并进行统计,其分布特征为:
这一步在IDL中通过编程实现,核心代码如下:
最后保存实验结果,代码为:
;输出结果
;u_result=u_result*255
;im6=image(u_result,MARGIN=0,title='waterview')
u_result=reverse(u_result,2)
ENVI_WRITE_ENVI_FILE,u_result, out_name='result.img', $ ;将图像存储在ENVI中去
map_info=map_info
该湖泊的最终实验结果如下:
以上实验为仅有两个湖泊的小区域,该实验完成之后,对整个区域进行该算法的实验,实验结果如下: