IDL对HDF5图像做GLT校正

最近需要对HY-1C的HDF5图像做几何校正,并简单的显示,但是查找了大量的资料,并没有找到相应的代码可供参考,只找到了一位朋友的博客,是对HDF影像做处理,在此感谢,地址在这儿http://blog.sina.com.cn/s/blog_afada1270101b97q.html

由于之前没有接触过IDL开发,于是我一边参考ENVI的帮助文档,一边自己摸索,终于满足需求,代码如下,希望大家做指正。(里面用到了大量的ENVI函数,原生的IDL开发,时间成本有点高,就没有采用)

PRO ENVI_GLT_DOIT_RECORD,_extra=extra
end

pro ENVI_GEOREFERENCE_FROM_GLT_DOIT_RECORD,extra=extra
end

PRO ENVI_GEOREF_FROM_GLT_DOIT_RECORD,extra=extra
end
;上边的代码,是因为我后期用到了C#\idl混合开发,用来处理错误的(参考董彦卿老师的博客)


pro readH5,Fname,WorkSpace
  
  compile_opt idl2
  ;处理ENVI命令,但不显示envi窗体
  e=ENVI(/headless)
  ;/on参数:显示处理进度条
  envi_batch_status_window, /on 
  ;设置输入投影
  inpro=ENVI_PROJ_CREATE(/geographic, datum="WGS-84")
  ;设置输出投影
  outpro=ENVI_PROJ_CREATE(/UTM, zone=51, datum="WGS-84")
  
  ;文件名
;Fname="C:\Users\ASUS\Desktop\1111\H1C_OPER_OCT_L1B_20191111T025000_20191111T025500_06164_10.h5"  

  file_id=H5F_open(Fname)
  ;打开群组
  groupData_id=H5G_OPEN(file_id,'Geophysical Data')
  groupGeo_id=H5G_OPEN(file_id,'Navigation Data')
  ;打开数据集
  datasetR_id=H5D_OPEN(groupData_id,'L_670')
  datasetG_id=H5D_OPEN(groupData_id,'L_865')
  datasetB_id=H5D_OPEN(groupData_id,'L_490')
  
  datasetLon_id=H5D_OPEN(groupGeo_id,'Longitude')
  datasetLat_id=H5D_OPEN(groupGeo_id,'Latitude')
  ;print,datasetLon_id,'  Lon_id'
  ;读取数据集中的shu'ju 
  sdsDataR=H5D_READ(datasetR_id)
  sdsDataG=H5D_READ(datasetG_id)
  sdsDataB=H5D_READ(datasetB_id)
  
  ;[206:1205]这个范围,是我所需的图像处理范围
  sdsDataRChnl=FLOAT(sdsDataR[206:1205,54:1458])
  sdsDataGChnl=FLOAT(sdsDataG[206:1205,54:1458])
  sdsDataBChnl=FLOAT(sdsDataB[206:1205,54:1458])
  sdsDataR=!null
  sdsDataG=!null
  sdsDataB=!null
  
  sdsDataLon=H5D_READ(datasetLon_id)
  sdsDataLat=H5D_READ(datasetLat_id)
  ;Help,sdsDataR
  ;help,sdsDataG
  ;help,sdsDataB
  
  LatChnl=FLOAT(sdsDataLat[206:1205,54:1458])
  LonChnl=FLOAT(sdsDataLon[206:1205,54:1458])
  sdsDataLon=!null
  sdsDataLat=!null
  
  ;处理Latitude波段
  ;判断文件是否存在,若存在,删除重新生成 
  ;RefLatTempFn=e.GetTemporaryFilename()
  RefLatTempFn=WorkSpace+'\RefLatTempFn.dat'
  resLat=file_test(RefLatTempFn)
  
  if resLat eq 1 then begin
    file_delete,RefLatTempFn
    ;file_Dir=file_Dirname(RefLatTempFn)
    RefLatTempHdr=WorkSpace+'\'+'RefLatTempFn.hdr'
    if file_test(RefLatTempHdr) eq 1 then begin
      file_delete,RefLatTempHdr
    endif
  endif
  
  RefLat=ENVIRaster(LatChnl,uri=RefLatTempFn)
  RefLat.Save
  ;print,'*******&&&&&&&&&*******'
  ;help,RefLat
  RefLat_id=ENVIRasterToFID(RefLat)
  LatChnl=!null

  ;处理Longitude波段
  ;RefLonTempFn=e.GetTemporaryFilename()
  RefLonTempFn=WorkSpace+'\RefLonTempFn.dat'
  resLon=file_test(RefLonTempFn)
  if resLon eq 1 then begin
    file_delete,RefLonTempFn
    Lonfile_dir=file_Dirname(RefLonTempFn)
    RefLonTempHdr=WorkSpace+'\'+'RefLonTempFn.hdr'
    if file_test(RefLonTempHdr) eq 1 then begin
      file_delete,RefLonTempHdr
    endif
  endif
  
  RefLon=ENVIRaster(LonChnl,uri=RefLonTempFn)
  RefLon.Save
  RefLon_id=ENVIRasterToFID(RefLon)
  ;print,RefLon_id
  ;help,RefLon_id
  LonChnl=!null
  

  ;生成数据数组,一维:R;二维:G;三维:B
  GeoDataChnl=MAKE_ARRAY([1000,1405,3],TYPE=4)
  FOR i=0,999 DO begin
    FOR j=0,1404 do begin
      ;R
      GeoDataChnl[i,j,0]=sdsDataRChnl[i,j]
      ;G
      GeoDataChnl[i,j,1]=sdsDataGChnl[i,j]
      ;B
      GeoDataChnl[i,j,2]=sdsDataBChnl[i,j]
    endfor
  endfor
 ;help,GeoDataChnl
 
 ;RefGeoDataTempFn=e.GetTemporaryFilename()
 RefGeoDataTempFn=WorkSpace+'\RefGeodata.dat'
 resGeoData=file_test(RefGeoDataTempFn)
 if resGeoData eq 1 then begin
  file_delete,RefGeoDataTempFn
  GeoDataFile_Dir=file_Dirname(RefGeoDataTempFn)
  RefGeoDataTempHdr=WorkSpace+'\'+'RefGeodata.hdr'
  if file_test(RefGeoDataTempHdr) eq 1 then begin
    file_delete,RefGeoDataTempHdr
  endif
 endif
    
 RefGeoData=ENVIRaster(GeoDataChnl,uri=RefGeoDataTempFn,interleave='BSQ')
 RefGeoData.Save
 RefGeoData_id=ENVIRasterToFID(RefGeoData)
 ;print,RefGeoData
 ;print,RefGeoData_id,'   RefGeoData_id'
 ;获取refGeoData_dims,用于下一步做GLT
 ENVI_FILE_QUERY,RefGeoData_id,dims=refGeoData_dims
 ;print,'*********overRead*************' 
 GeoDataChnl=!null
 
 ;生成GLT
 ;gltTempFn=e.GetTemporaryFileName()
 gltTempFn=WorkSpace+'\glt.dat'  
 ;RUN SOME APLICATION
 ENVI_DOIT,'ENVI_GLT_DOIT',DIMS=refGeoData_dims,I_PROJ=inpro,O_PROJ=outpro,$
    OUTNAME=gltTempFn,R_FID=glt_id,ROTATION=0,X_FID=RefLon_id,Y_FID=RefLat_id,$
    X_POS=[0],Y_POS=[0]
 ;print,'*********overGLT*************'
 
 
 glt_outname=WorkSpace+'\END_GLT.dat'
 resEndGlt=file_test(glt_outname)
 if resEndGlt eq 1 then begin
  file_delete,glt_outname
  ;endGltDir=file_Dirname(glt_outname)
  glt_outHdr=WorkSpace+'\'+'END_GLT.hdr'
  if file_test(glt_outHdr) eq 1 then begin
    file_delete,glt_outHdr
  endif
 endif
 

  ;做glt校正
 ENVI_DOIT,'ENVI_GEOREF_FROM_GLT_DOIT',$
      BACKGROUND=0,FID=RefGeoData_id,GLT_FID=glt_id,OUT_NAME=glt_outname,POS=[0:2]
      
 ;print,glt_outname
 ;print,'*********over*************'

  ;void=DIALOG_MESSAGE(!ERROR_STATE.MSG,/INFOR,TITLE='CW')
end

参考:http://www.harrisgeospatial.com/docs/ENVI_FILE_QUERY.html#DATA_TYPE

因为之前做AE开发的时候,就是有的功能不会做,就去用ArcGis desktop把思路走通,然后再用Arcengine做。这次做GLT几何校正,没想到也能实现。一些小感想:idl开发感觉就和matlab差不多,语言风格都相似,然而发现用idl做研究的居然不多,一位大佬告诉我,说国内外普遍用matlab+C++实现,要不这么难找idl资料呢。

下一篇文章,简单阐述一下C#+idl混合开发

IDL大数据分块实例代码,值得学习。 PRO WRITEREADHDF ;创建隐藏tlb,目的为了显示进度条 wtlb = WIDGET_BASE(map = 0) WIDGET_CONTROL,wtlb,/realize ;tlb居中显示 CENTERTLB,wtlb ;创建进度条 process = IDLITWDPROGRESSBAR( TIME=0,$ GROUP_LEADER=wtlb, $ TITLE='测试分块保存HDF... 请等待') IDLITWDPROGRESSBAR_SETVALUE, process, 0 ;源数据及相关信息 image = DIST(6000) ;求出数据范围 myRANGE=[MAX(image,min=min_xray),min_xray] dims = SIZE(image,/dimension) ;块大小 tileSize = [1024, 1024] ;初始化写入HDF数据 filename = 'c:\test.hdf' sd_id=HDF_SD_START(filename,/CREATE) ; sds_id=HDF_SD_CREATE(sd_id,'largeWrite', $ [dims[0],dims[1]],/FLOAT) ; HDF_SD_SETINFO,sds_id,FILL=0.0,LABEL='data', $ UNIT='float',$ RANGE=myRANGE ; ; Write labels to each of the dimension HDF_SD_DIMSET,HDF_SD_DIMGETID(sds_id,0),NAME='Width',LABEL='Width of data' HDF_SD_DIMSET,HDF_SD_DIMGETID(sds_id,1),NAME='Height',LABEL='Height of data' ;xn和yn分别是行、列的初始循环次数 xn = 0 yn = 0 ;计算循环次数,- 目的为了进度条正确显示 IF(dims[1]/tileSize[1] EQ 0 )AND(dims[0]/tileSize[0] EQ 0) THEN BEGIN TotalNum = 1 ENDIF ELSE IF(dims[1]/tileSize[1] EQ 0 ) THEN BEGIN TotalNum = FIX(dims[0]/tileSize[0])+1 ENDIF ELSE IF(dims[0]/tileSize[0] EQ 0 ) THEN BEGIN TotalNum = FIX(dims[1]/tileSize[1])+1 ENDIF ELSE TotalNum = (FIX(dims[1]/tileSize[1])+1)*(FIX(dims[0]/tileSize[0])+1) ; 更新下进度条 IDLITWDPROGRESSBAR_SETVALUE, process, 1 DoneNum = 0 UpRate = 99/TotalNum ;分别在水平和竖直方向循环 WHILE(yn LT FIX(dims[1]/tileSize[1])) DO BEGIN WHILE(xn LT FIX(dims[0]/tileSize[0])) DO BEGIN ;计算存储的数据块位置 loc = [tileSize[0]*xn,tileSize[1]*yn] ;提取数据相应位置数据 wtImg = image[loc[0]:(loc[0]+tilesize[0]-1),loc[1]:(loc[1]+tilesize[1]-1)] ;写入HDF文件中 HDF_SD_ADDDATA, sds_id, wtImg, $ START=loc, COUNT=tileSize xn++ ;更新进度条 DoneNum = DoneNum+1 IDLITWDPROGRESSBAR_SETVALUE, process, 1+UpRate*DoneNum ENDWHILE ; IF(dims[0] GT tileSize[0]*xn)THEN BEGIN ;计算存储的数据块位置 loc = [tileSize[0]*xn,tileSize[1]*yn] ;提取数据相应位置数据 wtImg = image[loc[0]:(dims[0]-1),loc[1]:(loc[1]+tilesize[1]-1)] ;写入HDF文件中,注意count的变化 HDF_SD_ADDDATA, sds_id, wtImg, $ START=loc, COUNT=SIZE(wtImg,/dimension) ENDIF ; xn = 0 yn++ ;更新进度条 DoneNum = DoneNum+1 IDLITWDPROGRESSBAR_SETVALUE, process, 1+UpRate*DoneNum ENDWHILE ; 最后一行不完整的部分 IF(dims[1] GT tileSize[1]*yn)THEN BEGIN xn = 0 WHILE(xn LT FIX(dims[0] /tileSize[0])) DO BEGIN ;计算存储的数据块位置 loc = [tileSize[0]*xn,tileSize[1]*yn] ;提取数据相应位置数据 wtImg = image[loc[0]:(dims[0]-1),loc[1]:(dims[1]-1)] ;写入HDF文件中 HDF_SD_ADDDATA, sds_id, wtImg, $ START=loc, COUNT=SIZE(wtImg,/dimension) xn++ ;更新进度条 DoneNum = DoneNum+1 IDLITWDPROGRESSBAR_SETVALUE, process, 1+UpRate*DoneNum ENDWHILE ENDIF ;关闭HDF HDF_SD_ENDACCESS,sds_id HDF_SD_END,sd_id IDLITWDPROGRESSBAR_SETVALUE, process, 100 ;销毁没用的 WAIT,0.3 WIDGET_CONTROL,process,/Destroy WIDGET_CONTROL, wtlb,/DESTROY END
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值