就是上次的那个完成作业工具。这次我把他写完了。有了这个工具这样子班主任大一布置的作业,一下子就很容易的完成了。困难重重,弄了好几天,有两个小错误一直卡着我。但是最终还是实现了地表温度反演,虽然不一定很准。如果说下一步需要改进的话,一方面是高效的问题,另一方面就是窗口的在运算结束后自动消除问题,还有一方面就是进度条的问题,这些问题我还没研究。
现在的功能是:能完成归一化植被指数,归一化水体指数,归一化建筑指数,归一化雪指数的计算。能完成Landsat8的地表温度反演。只能是landsat8哦!
我希望有高手能指点指点我的代码问题在哪里。
;
;Author:大圣
;
PRO author,ev
COMPILE_OPT idl2
;
!NULL=DIALOG_MESSAGE('大圣,版本:1.0')
;
END
;
PRO parameters_in,ev
COMPILE_OPT idl2
;
widget_control,ev.top,show=0
wtop=WIDGET_BASE(title='参数输入',xoffset=800,yoffset=200,xsize=250,ysize=165,/column)
;利用cw_field组合控件让使用者自行输出参数
cf1=cw_field(wtop,title=' 透过率t: ')
cf2=cw_field(wtop,title='大气向上辐射亮度Lu:')
cf3=cw_field(wtop,title='大气向下辐射亮度Ld:')
;widget_text利用/wrap实现自动换行
wt1=WIDGET_TEXT(wtop,value='请复制查询参数信息,选取2、3、5按钮 https://atmcorr.gsfc.nasa.gov/',$
/editable,ysize=2,/wrap)
;
;
wb1=WIDGET_BUTTON(wtop,value='确定',event_pro='Cal_LST')
;注意此处将各个cf_field的参数利用结构体进行传递,用指针也行
;用普通变量是不行的
struc={TLB:wtop,T:cf1,U:cf2,D:cf3}
WIDGET_CONTROL,wb1,set_uvalue=struc
WIDGET_CONTROL,wtop,/realize
;
;
END
;
;
PRO cal_LST,ev
COMPILE_OPT idl2
;将传进来的参数获取
e=ENVI(/current)
WIDGET_CONTROL,ev.ID,get_uvalue=struc
WIDGET_CONTROL,struc.T,get_value=t
WIDGET_CONTROL,struc.U,get_value=up
WIDGET_CONTROL,struc.D,get_value=down
!NULL=DIALOG_MESSAGE('请选择MTL文件!')
fn=ENVI_PICKFILE(title='请选择MTL文件!',filter='*mtl.txt')
IF fn EQ !NULL THEN RETURN
raster=e.openraster(fn)
;利用envitask进行处理
task=ENVITASK('radiometriccalibration')
task.INPUT_RASTER=raster[0]
task.SCALE_FACTOR=0.1
task.execute
MTL1=task.OUTPUT_RASTER
;
task=ENVITASK('radiometriccalibration')
task.INPUT_RASTER=raster[3]
task.SCALE_FACTOR=1
task.execute
Thermal=task.OUTPUT_RASTER
;
task=ENVITASK('quac')
task.INPUT_RASTER=MTL1
task.execute
quac=task.OUTPUT_RASTER
;
task=ENVITASK('spectralindex')
task.INPUT_RASTER=quac
task.INDEX='Normalized Difference Vegetation Index'
task.Execute
NDVI_raster=task.OUTPUT_RASTER
;利用e.getdata方法获取图像矩阵,计算植被覆盖度
NDVI=ndvi_raster.getdata(bands=[0])
Pv=ndvi_Raster.getdata(bands=[0])
w=WHERE(pv GT 0.7,count)
IF count GT 0 THEN pv[w]=1
w=WHERE(pv LT 0.05,count)
IF count GT 0 THEN pv[w]=0
w=WHERE(pv GE 0.05 AND pv LE 0.7,count)
IF count GT 0 THEN pv[w]=(pv[w]-0.05)/(0.65)
;计算地表比辐射率
r=pv
w= WHERE(ndvi LE 0,count)
IF count GT 0 THEN r[w] = 0.995
w= WHERE(ndvi GE 0.7,count)
IF count GT 0 THEN r[w] = ( 0.9625+0.0614*pv[w]-0.0461*pv[w]^2 )
w= where (ndvi GT 0 AND ndvi LT 0.7,count)
IF count GT 0 THEN r[w]=(0.9589 + 0.086*pv[w] -0.0671* pv[w]^2 )
;将无用了的变量消掉,节省内存空间
pv=!null
w=!null
;将传进来的字符串转化为浮点数组
the=thermal.getdata(bands=[0])
up1=FLOAT(up)
t1=FLOAT(t)
down1=FLOAT(down)
;这上下这些东西卡了我两天时间,终于获取了参数。
up=!NULL
down=!NULL
t=!NULL
;获取数组首个元素,即参数
up=up1[0]
down=down1[0]
t=t1[0]
;计算辐射亮度
Radiance=(the - up - t*(1-r)*down)/(t*r)
;计算温度
temperature=(1321.0789/ALOG(774.8853/radiance+1))-273
;将矩阵保存为enviraster对象
temperature_raster=ENVIRASTER(temperature)
temperature_raster.save
;创建图层进行显示
view=e.getview()
layer=view.createlayer(temperature_raster)
;
!NULL=DIALOG_MESSAGE('Finish!')
END
;
;
PRO select,ev
COMPILE_OPT idl2
;
wtop=WIDGET_BASE(title='选择所需指数!',xoffset=750,yoffset=400,/row,xsize=250)
;
wlabel=WIDGET_LABEL(wtop,value='选取指数')
;
wdrop=WIDGET_COMBOBOX(wtop,value=['请选择所需指数','NDVI','NDWI','NDBI','NDSI'])
;
wb=WIDGET_BUTTON(wtop,value='确定',uvalue='ok',event_pro='spectral')
;
structure={INDEX:wdrop}
WIDGET_CONTROL,wb,set_uvalue=structure
WIDGET_CONTROL,wtop,/realize
;xmanager,'select',wtop,/no_block
END
;
;
;
PRO spectral,ev
COMPILE_OPT idl2
;
WIDGET_CONTROL,ev.ID,get_uvalue=structure
select=WIDGET_INFO(structure.INDEX,/COMBOBOX_GETTEXT)
;
IF select EQ '请选择所需指数' THEN BEGIN
!NULL=DIALOG_MESSAGE('请选择一种指数!',/error)
RETURN
ENDIF
;
e=ENVI()
dg=DIALOG_MESSAGE('开始计算指数',title='执行')
;
ui=e.UI
raster=ui.selectinputdata(/raster)
IF raster EQ !NULL THEN BEGIN
!NULL=DIALOG_MESSAGE('请选取相应波段影像',/error)
RETURN
ENDIF
;
;
task=ENVITASK('radiometriccalibration')
task.INPUT_RASTER=raster
task.SCALE_FACTOR=0.1
task.execute
;
;
Calibration=task.OUTPUT_RASTER
task=ENVITASK('quac')
task.INPUT_RASTER=Calibration
task.execute
QUAC_Raster=task.OUTPUT_RASTER
;
;
IF select EQ 'NDVI' THEN index='Normalized Difference Vegetation Index' $
ELSE IF select EQ 'NDWI' THEN index='Normalized Difference Water Index' $
ELSE IF select EQ 'NDBI' THEN index='Normalized Difference Built-Up Index'$
ELSE IF select EQ 'NDSI' THEN index='Normalized Difference Snow Index'
;
task=ENVITASK('SpectralIndex')
task.INPUT_RASTER=QUAC_Raster
task.INDEX=index
task.execute
;
Indexraster=task.OUTPUT_RASTER
;
!NULL=DIALOG_MESSAGE('请选择指数输出路径!')
;
o_fn=DIALOG_PICKFILE(title='save as',file=select)
;
;
!NULL=DIALOG_MESSAGE('请等待!')
;
INdexraster.export,o_fn,'envi'
;
indexfile=e.openraster(o_fn)
view=e.getview()
layer=view.createlayer(indexfile)
view.zoom,/full_extent
;
END
;
;
PRO Landsat_Process_Tool
COMPILE_OPT idl2
;编写界面控件
!NULL=DIALOG_MESSAGE('作者:测绘学院遥感18级大圣 Vertion:1.0',/center)
wtop=WIDGET_BASE(title='完成作业工具',mbar=mbar,/row,xsize=400,xoffset=800,yoffset=300)
;
wb1=WIDGET_BUTTON(mbar,value='功能',uvalue='process',xoffset=30,yoffset=30,xsize=60,ysize=60)
;
wb2=WIDGET_BUTTON(wb1,value='多种指数计算',uvalue='spectral',event_pro='select')
;
wb3=WIDGET_BUTTON(wb1,value='LANDSAT8大气矫正法地表温度反演',uvalue='LST',event_pro='parameters_in')
;
wb4=WIDGET_BUTTON(mbar,value='关于',uvalue='about')
;
wb5=WIDGET_BUTTON(wb4,value='作者',uname='author',event_pro='author')
;此界面没有任何参数需要传递
WIDGET_CONTROL,wtop,/realize
;
xmanager,'Landsat_Process_Tool',wtop,/no_block
;
END
反演出来是这个样子的温度分布,还比较正常。下一步要做一个精度验证,和modis的数据。
效果是这个样子的:
还有一个最重要的需要改进的点就是不能用快速大气校正,要调用FLAASH的接口,不过那样子程序就复杂了,用起来也不好使了,我还得看看。
我把它弄成了sav,这样子放到extentions里面就能用。链接:
https://pan.baidu.com/s/1v4VAhFIVDQNVunNAkmI4PQ
有需要可以看看,用的话可能不太好使。
这个算法都是来自此处介绍的基于大气校正法的地表温度反演。http://blog.sina.com.cn/s/blog_764b1e9d0102wa8s.html
还请高手指点。