IDL利用envi接口实现Landsat8地表温度反演以及常见指数计算(ENVI5.x全新编程模式)

就是上次的那个完成作业工具。这次我把他写完了。有了这个工具这样子班主任大一布置的作业,一下子就很容易的完成了。困难重重,弄了好几天,有两个小错误一直卡着我。但是最终还是实现了地表温度反演,虽然不一定很准。如果说下一步需要改进的话,一方面是高效的问题,另一方面就是窗口的在运算结束后自动消除问题,还有一方面就是进度条的问题,这些问题我还没研究。
现在的功能是:能完成归一化植被指数,归一化水体指数,归一化建筑指数,归一化雪指数的计算。能完成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的数据。
IDL利用envi接口实现Landsat8地表温度反演以及常见指数计算(ENVI5.x全新编程模式)_第1张图片
效果是这个样子的:IDL利用envi接口实现Landsat8地表温度反演以及常见指数计算(ENVI5.x全新编程模式)_第2张图片
还有一个最重要的需要改进的点就是不能用快速大气校正,要调用FLAASH的接口,不过那样子程序就复杂了,用起来也不好使了,我还得看看。
我把它弄成了sav,这样子放到extentions里面就能用。链接:
https://pan.baidu.com/s/1v4VAhFIVDQNVunNAkmI4PQ
有需要可以看看,用的话可能不太好使。
这个算法都是来自此处介绍的基于大气校正法的地表温度反演。http://blog.sina.com.cn/s/blog_764b1e9d0102wa8s.html
还请高手指点。

你可能感兴趣的:(IDL)