【IDL代码库】IDL实现MODIS HDF文件的几何校正(气溶胶系统)


一、介绍

MODIS HDF包含经纬度数据集,因此可以进行几何校正。系统使用的方法是先读取HDF中的经纬度数据集,然后建立51*51的GCP控制点(见图1),通过对GCP点的投影转换来对角度数据集和辐射定标后的科学数据集进行几何校正。在几何校正的过程中将角度数据重采样到1000*1000分辨率,以便后来进行气溶胶反演的时候,按行列号查找角度数据。

二、IDL源码

源码下载:http://pan.baidu.com/s/1dDcXOEP

;+

;:Description:

;    Describe the procedure.

;

;:Author: tiands@esrichina.com.cn

;

;:Date: 2013-9-5 11:10:27

;-

;;=======================================================================  ;;;  改程序实现对辐射校正后的科学数据几何校正以及对角度数据校正,输出控制点文件  ;;;======================================================================  PRO MODIS_REGISTER,filename,fs_name,outname_angle,outname_data,GCP1,GCP2    ENVI, /RESTORE_BASE_SAVE_FILES    ENVI_BATCH_INIT, LOG_FILE = 'batch_log.txt'    COMPILE_OPT idl2        ;  filename ='H:\MODIS\modis数据\1km\MOD021KM.A2012126.0245.005.2012128183247.hdf'    ;  fs_name='C:\Users\tiandeshan\Desktop\idl\fushejiaozheng.img'    ;  outname_angle='C:\Users\tiandeshan\Desktop\idl\angledata.img'    ;  outname_data='C:\Users\tiandeshan\Desktop\idl\scaledata.img'    ;  GCP1='C:\Users\tiandeshan\Desktop\idl\GCP1.dat'    ;  GCP2='C:\Users\tiandeshan\Desktop\idl\GCP2.dat'            ;经纬度读取   Lon=READ_DATASET(filename,'Longitude')   Lat=READ_DATASET(filename,'Latitude')    ;重采样经纬度   ENVI_WRITE_ENVI_FILE,Lon[*,*],r_fid=fid_Lon,out_name='c:/temp'    FIDlon= MODIS_RESIZE(fid_Lon)    ENVI_FILE_QUERY, FIDlon,dims=dimslon    datalon = ENVI_GET_DATA(fid=FIDlon, dims=dimslon, pos=0)       ENVI_WRITE_ENVI_FILE,Lat[*,*],r_fid=fid_Lat,out_name='c:/temp'    FIDlat= MODIS_RESIZE(fid_Lat)    ENVI_FILE_QUERY, FIDlat,dims=dimslat    datalat = ENVI_GET_DATA(fid=FIDlat, dims=dimslat, pos=0)   ;;;=======================================================================    ;;;  GCP控制点建立   ;;;======================================================================   OPENW,lun,GCP1,/Get_lun    PRINTF,lun,' gcp[0,l] ','gcp[1,l] ','gcp[2,l]  ','gcp[2,l]  ','n  ','m  '    length=0L    ;定义控制点为51*51    gcp= DBLARR(4,2601)    rstr = ["Input File :" , "Output File :"]   ENVI_REPORT_INIT,rstr,title="output the GCP", base=base,/INTERRUPT    FOR i=3.5d,2030,40.53d DO BEGIN      FOR j=3.5d,1354,27.01d DO BEGIN       gcp[0,length]=datalon[j,i]       gcp[1,length]=datalat[j,i]       gcp[2,length]=j       gcp[3,length]=i       PRINTF,lun,gcp[0,length],gcp[1,length],gcp[2,length],gcp[3,length]       length=length+1L     ENDFOR     ENVI_REPORT_STAT, base, i*1354, 2601    ENDFOR    ENVI_REPORT_INIT, base=base, /finish    FREE_LUN,lun   ;;;=======================================================================    ;;;  GCP控制点投影转换   ;;;======================================================================   OPENW,lun,GCP2,/Get_lun   PRINTF,lun,'ogcp[0,l]','ogcp[1,l] ','ogcp[2,l]','ogcp[2,l]'    iproj= ENVI_PROJ_CREATE(/geographic)    units = envi_translate_projection_units('Meters')    datum = 'WGS-84'    oproj= ENVI_PROJ_CREATE(/utm, zone=51,datum=datum,units=units)   ENVI_CONVERT_PROJECTION_COORDINATES, gcp[0,*], gcp[1,*],iproj,outx, outy, oproj    ;    print,gcp[0,*]    ogcp= DBLARR(4,2601)    length=0L    FOR i=3.5d,2030,40.53d DO BEGIN      FOR j=3.5d,1354,27.01d DO BEGIN       ogcp[0,length]=outx[[(i-3.5)/40.53]*51+[(j-3.5)/27.01]]       ogcp[1,length]=outy[[(i-3.5)/40.53]*51+[(j-3.5)/27.01]]       ogcp[2,length]=gcp[2,length]       ogcp[3,length]=gcp[3,length]       PRINTF,lun,ogcp[0,length],ogcp[1,length],ogcp[2,length],ogcp[3,length]       length=length+1L     ENDFOR    ENDFOR    FREE_LUN,lun   ;;;=======================================================================    ;;; 开始校正   ;;;======================================================================    ;角度校正   OUT_BNAME=['Warp(SensorZenith)','Warp(SensorAzimuth)',$     'Warp(SolarZenith)','Warp(SolarAzimuth)']   anglefid=ANGLE_DATA(filename)   ENVI_FILE_QUERY,anglefid,nb=nb_angle,dims=dims_angle   REGISTER,anglefid,nb_angle,dims_angle,ogcp,oproj,outname_angle,OUT_BNAME    ;科学数据校正   OUT_BNAME=['Warp(1KM Reflectance (band1) [250 Aggr])','Warp(1KM Reflectance (band2) [250 Aggr])',$     'Warp(1KM Reflectance (band3) [500 Aggr])','Warp(1KM Reflectance (band4) [500 Aggr])','Warp(1KM Reflectance (band6) [500 Aggr])',$     'Warp(1KM Reflectance (band7) [500 Aggr])','Warp(1KM Reflectance (band8))','Warp(1KM Reflectance (band19))','Warp(1KM Reflectance (band26))',$     'Warp(1KM Emissive (band29))','Warp(1KM Emissive (band31))','Warp(1KM Emissive (band32))']           ;数据读取    IF (ENVI_IS_GDB(fs_name)) THEN BEGIN     ENVI_OPEN_GDB,fs_name,r_fid=data_fid    ENDIF ELSE BEGIN     ENVI_OPEN_FILE,fs_name,r_fid=data_fid    ENDELSE    ;envi_open_file, fs_name, r_fid=data_fid    ENVI_FILE_QUERY, data_fid, dims=dims_data, nb=nb_data   REGISTER,data_fid,nb_data,dims_data,ogcp,oproj,outname_data,OUT_BNAME    ENVI_BATCH_EXIT  END        FUNCTION  ANGLE_DATA,filename    COMPILE_OPT idl2    ;角度信息读取   sensorzenith=READ_DATASET(filename,'SensorZenith')   sensorazimuth=READ_DATASET(filename,'SensorAzimuth')   solarzenith=READ_DATASET(filename,'SolarZenith')   solarazimuth=READ_DATASET(filename,'SolarAzimuth')   ;;;=======================================================================    ;;;  角度信息合成   ;;;======================================================================   ENVI_WRITE_ENVI_FILE,sensorzenith[*,*],r_fid=fid_sez,/IN_MEMORY   ENVI_WRITE_ENVI_FILE,sensorazimuth[*,*],r_fid=fid_sea,/IN_MEMORY   ENVI_WRITE_ENVI_FILE,solarzenith[*,*],r_fid=fid_soz,/IN_MEMORY   ENVI_WRITE_ENVI_FILE,solarazimuth[*,*],r_fid=fid_soa,/IN_MEMORY   ENVI_FILE_QUERY,fid_sez,dims=sezdims   fid_sez_c=ANGLE_CALCULATE(fid_sez)   fid_sea_c=ANGLE_CALCULATE(fid_sea)   fid_soz_c=ANGLE_CALCULATE(fid_soz)   fid_soa_c=ANGLE_CALCULATE(fid_soa)   ;将四个有用信息的图像合成一个图像,便于后续的几何校正工作    ENVI_DOIT, 'cf_doit',fid=[fid_sez_c,fid_sea_c,fid_soz_c,fid_soa_c], $     pos=[0,0,0,0], dims=sezdims, $     remove=0,r_fid=info_fid ,/in_memory    ;将四个单独的几何信息文件释放    ENVI_FILE_MNG, id=fid_sez, /remove    ENVI_FILE_MNG, id=fid_sea, /remove    ENVI_FILE_MNG, id=fid_soz, /remove    ENVI_FILE_MNG, id=fid_soa, /remove    angle_fid= MODIS_RESIZE(info_fid)        RETURN,angle_fid  END      FUNCTION ANGLE_CALCULATE,fid    COMPILE_OPT idl2        ENVI_FILE_QUERY, fid, dims=dims    t_fid = [fid]    pos = [0]    ;表达式    exp='b1*0.0100'    ENVI_DOIT, 'math_doit', $     fid=t_fid, pos=pos, dims=dims,$     exp=exp,r_fid=r_fid, /IN_MEMORY    ENVI_FILE_MNG, id=fid, /remove    RETURN,r_fid  END          FUNCTION READ_DATASET,filename,dataset    SD_id = HDF_SD_START(filename)    index = HDF_SD_NAMETOINDEX(SD_id,dataset)   sds_id=HDF_SD_SELECT(SD_id,index)   HDF_SD_GETINFO,sds_id,DIMS=dim   HDF_SD_GETDATA,sds_id,data   HDF_SD_ENDACCESS,sds_id    RETURN,data  END        FUNCTION MODIS_RESIZE,fid    COMPILE_OPT IDL2    ; Open the input file    IF (fid EQ -1) THEN BEGIN     RETURN,-1    ENDIF    ENVI_FILE_QUERY, fid, dims=dims, nb=nb    pos = LINDGEN(nb)    out_name = 'testimg'    ;把数据集重采样成1354*2030    ENVI_DOIT, 'resize_doit', $     fid=fid, pos=pos, dims=dims, $     interp=1, rfact=[.20015,.2], $     out_name=out_name, r_fid=r_fid    RETURN,r_fid  END    PRO REGISTER,fid,nb,dims,ogcp,oproj,out_name,OUT_BNAME    COMPILE_OPT idl2    pos = LINDGEN(nb)    pixel_size = [1000.00,1000.00]    ENVI_DOIT, 'envi_register_doit', w_fid=fid, w_pos=pos,w_dims=dims,method=7,$     out_name=out_name,pts=ogcp, proj=oproj,r_fid=r_fid3,pixel_size=pixel_size,OUT_BNAME=OUT_BNAME    ENVI_FILE_MNG, id=r_fid3, /remove    ENVI_FILE_MNG, id=fid, /remove  END