MODIS图像批量镶嵌拼接方法(IDL/ENVI)

要编程才能进行的图像镶嵌拼接工作肯定是因为文件多,工作量大,手工操作几乎无法完成。
前辈们已经编写过用IDL/ENVI进行图像镶嵌的程序,粘贴了几个来试用后总感觉得到的结果赶不上用ENVI手工操作的结果,虽然这些程序也使用了ENVI的mosaic_doit方法。ENVI中的mosaicing到底是不是用mosaic_doit来做的啊?不管那么多,既然ENVI能做得好,搬用它的套路来做吧。
用mosaic_doit最麻烦的是参数设置,一大堆,IDL编程主要是获取这些参数。要获得跟ENVI手工拼出的图像一样的图形,其实思路很简单:用ENVI的参数!手工做一幅,这些参数就基本全了。所以,过程就是:
1、用ENVI手工拼一幅图,保存图像(用于提取地图信息)
2、在Map based Mosaic窗口的file菜单下保存拼接工作为模板(用于提取x0, y0坐标)
3、IDL简单编程,使用上面获得的地图和坐标信息进行拼接

得到的图像和ENVI手工拼接的完全一样。

pro MODIS_mosaicing
  compile_opt idl2
  envi,/restore_base_save_files
  envi_batch_init
  ;
  ;设置路径,按情况修改
  path = 'E:\D_RSensing\MODIS.NDV\NDV.original\'
outpath = 'E:\D_RSensing\MODIS.NDV\NDV.mosaic\'
  ;====================================================================
  ;- 先用envi手工拼接一幅图像mosaic.model.img作为结果模板
  ;- 从模板文件中获取 envi_doit需要的很多信息------------
  modfile = path + "mosaic.model.img"
  envi_open_file, modfile, r_fid=fid
  envi_file_query,fid, dims=dims, ns=ns, nl=nl, data_type=data_type
  map_info = envi_get_map_info(fid=fid)   ;envi_doit参数
  envi_file_mng,id=fid,/remove
  pixel_size = map_info.ps[0:1]     ;envi_doit参数
  xsize = ns*map_info.ps[0]   ;envi_doit参数
  ysize = nl*map_info.ps[1]   ;envi_doit参数
  ;
  ;====================================================================
  ;- 由于windows的限制,用dialog_pickfile不能选择太多的文件,
  ;- 要批量处理以万计的文件得先建好文件名解析的列表文件,这个需要自己去做
  openr,lun,path + '0.datelist.txt', /get_lun
  datelist = ''
  thedate = ''
  while not eof(lun) do begin & $
    readf,lun, thedate & $
    datelist = [datelist, thedate]
  endwhile
  free_lun, lun
  close,lun
 
  openr,lun,path + '0.loclist.txt', /get_lun
  loclist = ''
  theloc = ''
  while not eof(lun) do begin & $
    readf,lun, theloc & $
    loclist = [loclist, theloc]
  endwhile
  free_lun, lun
  close,lun
  datelist = datelist[1:*]
  loclist = loclist[1:*]
  ndate = size(datelist, /n_elements)     ;文件名中的日期信息,modis原样
  nloc = size(locList, /n_elements)       ;文件名中的坐标信息,以字符开头
  ;
  ;下面这个是从ENVI手工拼接保存的模板文件中提取的信息
  openr,lun,path + '0.x0y0.txt', /get_lun
  x0y0 = fltarr(2, nloc)
  readf,lun, x0y0
  free_lun, lun
  close,lun
  x0 = reform(x0y0[0,*])   ;envi_doit参数
  y0 = reform(x0y0[1,*])   ;envi_doit参数
  ;
  ;====================================================================
  ;NDVI/EVI图像只能按相同日期进行拼接,只好按日期进行循环了
  for datendx=0, ndate-1 do begin
    ndv_files = path + 'NDVI.' + datelist[datendx] + '.' + loclist + '.tif'
    result_file = outpath + 'NDVI.' + datelist[datendx] + '.img'
    see_throuth_files = lonarr(nloc) + 1L
    see_throuth_value = fltarr(nloc)  ;按自己图像的背景值设定
    background = see_throuth_value[0]
    dims=lonarr(5, nloc)   ;envi_doit参数
    pos = lonarr(1,nloc)   ;envi_doit参数,不用赋值,因为每个文件都是一个波段pos=0
    fids = lonarr(nloc)    ;envi_doit参数
    for i=0,nloc-1 do begin
      envi_open_file, ndv_files[i], r_fid=fidx
      envi_file_query,fidx,ns=nsx,nl=nlx
      mapinfo = envi_get_map_info(fid=fidx)
      fids[i]=fidx
      dims[*,i]=[-1,0, nsx-1,0, nlx-1]
    endfor
    ;
    envi_doit, 'mosaic_doit', fid=fids, out_name=result_file, $
      dims=dims, pos=pos, xsize=xsize, ysize=ysize, $
      x0=x0, y0=y0, pixel_size=pixel_size, $
      out_dt=4, background=background, georef=1, map_info=map_info, $
      see_through_val=see_throuth_value, use_see_through=see_throuth_files
      ;
      for i=0, nloc-1 do envi_file_mng,id=fids[i],/remove
  endfor; loops of datendx
  ;
  envi_batch_exit
  dlg = dialog_message("work done!")
end

顺便贴出用到的三个数据文件的生成代码(R语言脚本):

#tiff文件名应该包含经纬度和日期信息,否则不好批量处理
setwd(choose.dir(default = "D:/", caption = "选择tif文件所在文件夹"))
tif.files <- list.files('.', pattern="NDVI.*\\.tif$")  #如果不是NDVI文件,改前缀就可以了
n <- length(tif.files)
dateList <- NULL
locList <- NULL
#我的NDVI文件命名模式是:NDVI.Axxxxxx.NExxxx.tif
#点号分隔第二部分为MODIS影像日期,第三部分是添加的经纬度信息
#日期和经纬度就可以用下面循环代码提取
for(i in 1:n){
    fileinfo <- unlist(strsplit(tif.files[i], '.', fixed=T))
    dateList <- c(dateList, fileinfo[2])
    locList <- c(locList, fileinfo[3])
}
dateList <- sort(unique(dateList))
locList <- sort(unique(locList))
write(dateList, "0.datelist.txt", ncolumns = 1)
write(locList, "0.loclist.txt", ncolumns = 1)

#选择预先拼接和保存的模板文件,从中读取出x0y0信息
the.filter <- matrix(c(".mos", "*.mos", "All (*.*)", "*.*"),  ncol = 2, byrow = T)
mosfile <- choose.files(caption = "Select mos file", filters = the.filter, index = 1)
model <- readLines(mosfile)
locs <- model[grepl("^File.+", model)]
locs <- gsub(".+(NE\\d+)\\.tif$", "\\1", locs)
xy <- model[grepl("^Info.+", model)]
xy <- gsub("^Info.*\\((.+)\\).+", "\\1", xy)
names(xy) <- locs
xy <- xy[locList]
write.table(xy, "0.x0y0.txt", row.names = F, col.names = F, quote=F)
winDialog(type="ok", message="Done")


如果手头没有合适的文件批量重命名工具,可以使用下面的R语言代码进行文件批量更名。警告:使用时先拷贝几个文件到新文件夹试试,以免出错后无法恢复原信息!

setwd(choose.dir(default = "D:/", caption = "选择tif文件所在文件夹"))
#下面是图像的经纬度标识,要添加到文件名中。每个MODIS压缩文件应解压到独立文件夹
lonlat <- "NE360955"
#下面语句选择要更名的文件,根据数据类型做相应修改(“NDVI”改成相应的名称)
orifiles <- list.files('.', pattern=".*NDVI.*\\.tif$")
#提取每个文件的日期信息,根据MODIS产品类型修改前缀(MOD13Q1部分)
dateinfo <- gsub("MOD13Q1\\.([^\\.]+)\\..+$", "\\1", orifiles)
#产生新的文件名,自己改吧
finals <- paste("NDVI", dateinfo, lonlat, "tif", sep=".")
n <- length(orifiles)
#文件重命名的代码
for(i in 1:n){
    if(file.exists(finals[i])){
        print(paste("文件", finals[i], "已存在,未修改!")
        next
    }
    file.rename(orifiles[i], finals[i])
}
winDialog(type="ok", message="Done")

你可能感兴趣的:(ENVI,IDL,ENVI,IDL)